]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix SysCacheGetAttr() to handle the case where the specified syscache has not
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 6 Oct 2006 18:23:48 +0000 (18:23 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 6 Oct 2006 18:23:48 +0000 (18:23 +0000)
been initialized yet.  This can happen because there are code paths that call
SysCacheGetAttr() on a tuple originally fetched from a different syscache
(hopefully on the same catalog) than the one specified in the call.  It
doesn't seem useful or robust to try to prevent that from happening, so just
improve the function to cope instead.  Per bug#2678 from Jeff Trout.  The
specific example shown by Jeff is new in 8.1, but to be on the safe side
I'm backpatching 8.0 as well.  We could patch 7.x similarly but I think
that's probably overkill, given the lack of evidence of old bugs of this ilk.

src/backend/utils/cache/catcache.c
src/backend/utils/cache/syscache.c
src/include/utils/catcache.h

index 68995f9838827fdff9f9aab0a104d6282f8b6a57..0cd30ed85263bb981b66158efad41211dadd82e9 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/cache/catcache.c,v 1.118 2004/12/31 22:01:25 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/cache/catcache.c,v 1.118.4.1 2006/10/06 18:23:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -972,7 +972,7 @@ CatalogCacheInitializeCache(CatCache *cache)
                cache->cc_skey[i].sk_strategy = BTEqualStrategyNumber;
                cache->cc_skey[i].sk_subtype = InvalidOid;
 
-               CACHE4_elog(DEBUG2, "CatalogCacheInit %s %d %p",
+               CACHE4_elog(DEBUG2, "CatalogCacheInitializeCache %s %d %p",
                                        cache->cc_relname,
                                        i,
                                        cache);
@@ -987,18 +987,20 @@ CatalogCacheInitializeCache(CatCache *cache)
 /*
  * InitCatCachePhase2 -- external interface for CatalogCacheInitializeCache
  *
- * The only reason to call this routine is to ensure that the relcache
- * has created entries for all the catalogs and indexes referenced by
- * catcaches.  Therefore, open the index too.  An exception is the indexes
- * on pg_am, which we don't use (cf. IndexScanOK).
+ * One reason to call this routine is to ensure that the relcache has
+ * created entries for all the catalogs and indexes referenced by catcaches.
+ * Therefore, provide an option to open the index as well as fixing the
+ * cache itself.  An exception is the indexes on pg_am, which we don't use
+ * (cf. IndexScanOK).
  */
 void
-InitCatCachePhase2(CatCache *cache)
+InitCatCachePhase2(CatCache *cache, bool touch_index)
 {
        if (cache->cc_tupdesc == NULL)
                CatalogCacheInitializeCache(cache);
 
-       if (cache->id != AMOID &&
+       if (touch_index &&
+               cache->id != AMOID &&
                cache->id != AMNAME)
        {
                Relation        idesc;
index 3435ac8ee0c6b3dd44d99256f1b27567dc784875..2ed6d55b83c4f217730cac72131d570e500b5693 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.96 2004/12/31 22:01:25 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.96.4.1 2006/10/06 18:23:47 tgl Exp $
  *
  * NOTES
  *       These routines allow the parser/planner/executor to perform
@@ -495,7 +495,7 @@ InitCatalogCachePhase2(void)
        Assert(CacheInitialized);
 
        for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
-               InitCatCachePhase2(SysCache[cacheId]);
+               InitCatCachePhase2(SysCache[cacheId], true);
 }
 
 
@@ -692,6 +692,9 @@ SearchSysCacheExistsAttName(Oid relid, const char *attname)
  * As with heap_getattr(), if the attribute is of a pass-by-reference type
  * then a pointer into the tuple data area is returned --- the caller must
  * not modify or pfree the datum!
+ *
+ * Note: it is legal to use SysCacheGetAttr() with a cacheId referencing
+ * a different cache for the same catalog the tuple was fetched from.
  */
 Datum
 SysCacheGetAttr(int cacheId, HeapTuple tup,
@@ -699,16 +702,19 @@ SysCacheGetAttr(int cacheId, HeapTuple tup,
                                bool *isNull)
 {
        /*
-        * We just need to get the TupleDesc out of the cache entry, and then
-        * we can apply heap_getattr().  We expect that the cache control data
-        * is currently valid --- if the caller recently fetched the tuple,
-        * then it should be.
+        * We just need to get the TupleDesc out of the cache entry, and then we
+        * can apply heap_getattr().  Normally the cache control data is already
+        * valid (because the caller recently fetched the tuple via this same
+        * cache), but there are cases where we have to initialize the cache here.
         */
-       if (cacheId < 0 || cacheId >= SysCacheSize)
+       if (cacheId < 0 || cacheId >= SysCacheSize ||
+               !PointerIsValid(SysCache[cacheId]))
                elog(ERROR, "invalid cache id: %d", cacheId);
-       if (!PointerIsValid(SysCache[cacheId]) ||
-               !PointerIsValid(SysCache[cacheId]->cc_tupdesc))
-               elog(ERROR, "missing cache data for cache id %d", cacheId);
+       if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
+       {
+               InitCatCachePhase2(SysCache[cacheId], false);
+               Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
+       }
 
        return heap_getattr(tup, attributeNumber,
                                                SysCache[cacheId]->cc_tupdesc,
index f08212d3f38921d2cc938347f3ffbb199691c141..21c1e1b8c66b8a83bdb2039f3d61b1fcdfa3a3f1 100644 (file)
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/catcache.h,v 1.52 2004/12/31 22:03:45 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/utils/catcache.h,v 1.52.4.1 2006/10/06 18:23:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -167,7 +167,7 @@ extern void AtEOXact_CatCache(bool isCommit);
 extern CatCache *InitCatCache(int id, const char *relname, const char *indname,
                         int reloidattr,
                         int nkeys, const int *key);
-extern void InitCatCachePhase2(CatCache *cache);
+extern void InitCatCachePhase2(CatCache *cache, bool touch_index);
 
 extern HeapTuple SearchCatCache(CatCache *cache,
                           Datum v1, Datum v2,