]> granicus.if.org Git - postgresql/blobdiff - src/backend/utils/cache/catcache.c
pgindent run for 9.0, second run
[postgresql] / src / backend / utils / cache / catcache.c
index a52882592c81fd67b663ed0dc0d027ad25ac1a2f..da89c8a7e4c2018eadeb2b2e6f7447e28826d8af 100644 (file)
@@ -3,12 +3,12 @@
  * catcache.c
  *       System catalog cache for tuples matching a key.
  *
- * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/cache/catcache.c,v 1.142 2008/03/26 21:10:39 alvherre Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/cache/catcache.c,v 1.153 2010/07/06 19:18:58 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,6 +17,8 @@
 #include "access/genam.h"
 #include "access/hash.h"
 #include "access/heapam.h"
+#include "access/relscan.h"
+#include "access/sysattr.h"
 #include "access/valid.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_type.h"
@@ -26,8 +28,9 @@
 #endif
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
+#include "utils/inval.h"
 #include "utils/memutils.h"
-#include "utils/relcache.h"
+#include "utils/rel.h"
 #include "utils/resowner.h"
 #include "utils/syscache.h"
 #include "utils/tqual.h"
@@ -102,30 +105,37 @@ GetCCHashEqFuncs(Oid keytype, PGFunction *hashfunc, RegProcedure *eqfunc)
        {
                case BOOLOID:
                        *hashfunc = hashchar;
+
                        *eqfunc = F_BOOLEQ;
                        break;
                case CHAROID:
                        *hashfunc = hashchar;
+
                        *eqfunc = F_CHAREQ;
                        break;
                case NAMEOID:
                        *hashfunc = hashname;
+
                        *eqfunc = F_NAMEEQ;
                        break;
                case INT2OID:
                        *hashfunc = hashint2;
+
                        *eqfunc = F_INT2EQ;
                        break;
                case INT2VECTOROID:
                        *hashfunc = hashint2vector;
+
                        *eqfunc = F_INT2VECTOREQ;
                        break;
                case INT4OID:
                        *hashfunc = hashint4;
+
                        *eqfunc = F_INT4EQ;
                        break;
                case TEXTOID:
                        *hashfunc = hashtext;
+
                        *eqfunc = F_TEXTEQ;
                        break;
                case OIDOID:
@@ -138,15 +148,18 @@ GetCCHashEqFuncs(Oid keytype, PGFunction *hashfunc, RegProcedure *eqfunc)
                case REGCONFIGOID:
                case REGDICTIONARYOID:
                        *hashfunc = hashoid;
+
                        *eqfunc = F_OIDEQ;
                        break;
                case OIDVECTOROID:
                        *hashfunc = hashoidvector;
+
                        *eqfunc = F_OIDVECTOREQ;
                        break;
                default:
                        elog(FATAL, "type %u not supported as catcache key", keytype);
                        *hashfunc = NULL;       /* keep compiler quiet */
+
                        *eqfunc = InvalidOid;
                        break;
        }
@@ -213,7 +226,7 @@ CatalogCacheComputeHashValue(CatCache *cache, int nkeys, ScanKey cur_skey)
 static uint32
 CatalogCacheComputeTupleHashValue(CatCache *cache, HeapTuple tuple)
 {
-       ScanKeyData cur_skey[4];
+       ScanKeyData cur_skey[CATCACHE_MAXKEYS];
        bool            isNull = false;
 
        /* Copy pre-initialized overhead data for scankey */
@@ -660,107 +673,43 @@ ResetCatalogCaches(void)
 }
 
 /*
- *             CatalogCacheFlushRelation
+ *             CatalogCacheFlushCatalog
  *
- *     This is called by RelationFlushRelation() to clear out cached information
- *     about a relation being dropped.  (This could be a DROP TABLE command,
- *     or a temp table being dropped at end of transaction, or a table created
- *     during the current transaction that is being dropped because of abort.)
- *     Remove all cache entries relevant to the specified relation OID.
- *
- *     A special case occurs when relId is itself one of the cacheable system
- *     tables --- although those'll never be dropped, they can get flushed from
- *     the relcache (VACUUM causes this, for example).  In that case we need
- *     to flush all cache entries that came from that table.  (At one point we
- *     also tried to force re-execution of CatalogCacheInitializeCache for
- *     the cache(s) on that table.  This is a bad idea since it leads to all
+ *     Flush all catcache entries that came from the specified system catalog.
+ *     This is needed after VACUUM FULL/CLUSTER on the catalog, since the
+ *     tuples very likely now have different TIDs than before.  (At one point
+ *     we also tried to force re-execution of CatalogCacheInitializeCache for
+ *     the cache(s) on that catalog.  This is a bad idea since it leads to all
  *     kinds of trouble if a cache flush occurs while loading cache entries.
  *     We now avoid the need to do it by copying cc_tupdesc out of the relcache,
  *     rather than relying on the relcache to keep a tupdesc for us.  Of course
  *     this assumes the tupdesc of a cachable system table will not change...)
  */
 void
-CatalogCacheFlushRelation(Oid relId)
+CatalogCacheFlushCatalog(Oid catId)
 {
        CatCache   *cache;
 
-       CACHE2_elog(DEBUG2, "CatalogCacheFlushRelation called for %u", relId);
+       CACHE2_elog(DEBUG2, "CatalogCacheFlushCatalog called for %u", catId);
 
        for (cache = CacheHdr->ch_caches; cache; cache = cache->cc_next)
        {
-               int                     i;
-
                /* We can ignore uninitialized caches, since they must be empty */
                if (cache->cc_tupdesc == NULL)
                        continue;
 
-               /* Does this cache store tuples of the target relation itself? */
-               if (cache->cc_tupdesc->attrs[0]->attrelid == relId)
+               /* Does this cache store tuples of the target catalog? */
+               if (cache->cc_tupdesc->attrs[0]->attrelid == catId)
                {
                        /* Yes, so flush all its contents */
                        ResetCatalogCache(cache);
-                       continue;
-               }
-
-               /* Does this cache store tuples associated with relations at all? */
-               if (cache->cc_reloidattr == 0)
-                       continue;                       /* nope, leave it alone */
 
-               /* Yes, scan the tuples and remove those related to relId */
-               for (i = 0; i < cache->cc_nbuckets; i++)
-               {
-                       Dlelem     *elt,
-                                          *nextelt;
-
-                       for (elt = DLGetHead(&cache->cc_bucket[i]); elt; elt = nextelt)
-                       {
-                               CatCTup    *ct = (CatCTup *) DLE_VAL(elt);
-                               Oid                     tupRelid;
-
-                               nextelt = DLGetSucc(elt);
-
-                               /*
-                                * Negative entries are never considered related to a rel,
-                                * even if the rel is part of their lookup key.
-                                */
-                               if (ct->negative)
-                                       continue;
-
-                               if (cache->cc_reloidattr == ObjectIdAttributeNumber)
-                                       tupRelid = HeapTupleGetOid(&ct->tuple);
-                               else
-                               {
-                                       bool            isNull;
-
-                                       tupRelid =
-                                               DatumGetObjectId(fastgetattr(&ct->tuple,
-                                                                                                        cache->cc_reloidattr,
-                                                                                                        cache->cc_tupdesc,
-                                                                                                        &isNull));
-                                       Assert(!isNull);
-                               }
-
-                               if (tupRelid == relId)
-                               {
-                                       if (ct->refcount > 0 ||
-                                               (ct->c_list && ct->c_list->refcount > 0))
-                                       {
-                                               ct->dead = true;
-                                               /* parent list must be considered dead too */
-                                               if (ct->c_list)
-                                                       ct->c_list->dead = true;
-                                       }
-                                       else
-                                               CatCacheRemoveCTup(cache, ct);
-#ifdef CATCACHE_STATS
-                                       cache->cc_invals++;
-#endif
-                               }
-                       }
+                       /* Tell inval.c to call syscache callbacks for this cache */
+                       CallSyscacheCallbacks(cache->id, NULL);
                }
        }
 
-       CACHE1_elog(DEBUG2, "end of CatalogCacheFlushRelation call");
+       CACHE1_elog(DEBUG2, "end of CatalogCacheFlushCatalog call");
 }
 
 /*
@@ -786,7 +735,6 @@ CatCache *
 InitCatCache(int id,
                         Oid reloid,
                         Oid indexoid,
-                        int reloidattr,
                         int nkeys,
                         const int *key,
                         int nbuckets)
@@ -850,7 +798,6 @@ InitCatCache(int id,
        cp->cc_indexoid = indexoid;
        cp->cc_relisshared = false; /* temporary */
        cp->cc_tupdesc = (TupleDesc) NULL;
-       cp->cc_reloidattr = reloidattr;
        cp->cc_ntup = 0;
        cp->cc_nbuckets = nbuckets;
        cp->cc_nkeys = nkeys;
@@ -1034,34 +981,55 @@ InitCatCachePhase2(CatCache *cache, bool touch_index)
  *             certain system indexes that support critical syscaches.
  *             We can't use an indexscan to fetch these, else we'll get into
  *             infinite recursion.  A plain heap scan will work, however.
- *
  *             Once we have completed relcache initialization (signaled by
  *             criticalRelcachesBuilt), we don't have to worry anymore.
+ *
+ *             Similarly, during backend startup we have to be able to use the
+ *             pg_authid and pg_auth_members syscaches for authentication even if
+ *             we don't yet have relcache entries for those catalogs' indexes.
  */
 static bool
 IndexScanOK(CatCache *cache, ScanKey cur_skey)
 {
-       if (cache->id == INDEXRELID)
+       switch (cache->id)
        {
-               /*
-                * Rather than tracking exactly which indexes have to be loaded before
-                * we can use indexscans (which changes from time to time), just force
-                * all pg_index searches to be heap scans until we've built the
-                * critical relcaches.
-                */
-               if (!criticalRelcachesBuilt)
+               case INDEXRELID:
+
+                       /*
+                        * Rather than tracking exactly which indexes have to be loaded
+                        * before we can use indexscans (which changes from time to time),
+                        * just force all pg_index searches to be heap scans until we've
+                        * built the critical relcaches.
+                        */
+                       if (!criticalRelcachesBuilt)
+                               return false;
+                       break;
+
+               case AMOID:
+               case AMNAME:
+
+                       /*
+                        * Always do heap scans in pg_am, because it's so small there's
+                        * not much point in an indexscan anyway.  We *must* do this when
+                        * initially building critical relcache entries, but we might as
+                        * well just always do it.
+                        */
                        return false;
-       }
-       else if (cache->id == AMOID ||
-                        cache->id == AMNAME)
-       {
-               /*
-                * Always do heap scans in pg_am, because it's so small there's not
-                * much point in an indexscan anyway.  We *must* do this when
-                * initially building critical relcache entries, but we might as well
-                * just always do it.
-                */
-               return false;
+
+               case AUTHNAME:
+               case AUTHOID:
+               case AUTHMEMMEMROLE:
+
+                       /*
+                        * Protect authentication lookups occurring before relcache has
+                        * collected entries for shared indexes.
+                        */
+                       if (!criticalSharedRelcachesBuilt)
+                               return false;
+                       break;
+
+               default:
+                       break;
        }
 
        /* Normal case, allow index scan */
@@ -1091,7 +1059,7 @@ SearchCatCache(CatCache *cache,
                           Datum v3,
                           Datum v4)
 {
-       ScanKeyData cur_skey[4];
+       ScanKeyData cur_skey[CATCACHE_MAXKEYS];
        uint32          hashValue;
        Index           hashIndex;
        Dlelem     *elt;
@@ -1332,7 +1300,7 @@ SearchCatCacheList(CatCache *cache,
                                   Datum v3,
                                   Datum v4)
 {
-       ScanKeyData cur_skey[4];
+       ScanKeyData cur_skey[CATCACHE_MAXKEYS];
        uint32          lHashValue;
        Dlelem     *elt;
        CatCList   *cl;
@@ -1450,7 +1418,7 @@ SearchCatCacheList(CatCache *cache,
 
                scandesc = systable_beginscan(relation,
                                                                          cache->cc_indexoid,
-                                                                         true,
+                                                                         IndexScanOK(cache, cur_skey),
                                                                          SnapshotNow,
                                                                          nkeys,
                                                                          cur_skey);
@@ -1671,16 +1639,16 @@ build_dummy_tuple(CatCache *cache, int nkeys, ScanKey skeys)
        HeapTuple       ntp;
        TupleDesc       tupDesc = cache->cc_tupdesc;
        Datum      *values;
-       char       *nulls;
+       bool       *nulls;
        Oid                     tupOid = InvalidOid;
        NameData        tempNames[4];
        int                     i;
 
        values = (Datum *) palloc(tupDesc->natts * sizeof(Datum));
-       nulls = (char *) palloc(tupDesc->natts * sizeof(char));
+       nulls = (bool *) palloc(tupDesc->natts * sizeof(bool));
 
        memset(values, 0, tupDesc->natts * sizeof(Datum));
-       memset(nulls, 'n', tupDesc->natts * sizeof(char));
+       memset(nulls, true, tupDesc->natts * sizeof(bool));
 
        for (i = 0; i < nkeys; i++)
        {
@@ -1693,7 +1661,7 @@ build_dummy_tuple(CatCache *cache, int nkeys, ScanKey skeys)
                         * Here we must be careful in case the caller passed a C string
                         * where a NAME is wanted: convert the given argument to a
                         * correctly padded NAME.  Otherwise the memcpy() done in
-                        * heap_formtuple could fall off the end of memory.
+                        * heap_form_tuple could fall off the end of memory.
                         */
                        if (cache->cc_isname[i])
                        {
@@ -1703,7 +1671,7 @@ build_dummy_tuple(CatCache *cache, int nkeys, ScanKey skeys)
                                keyval = NameGetDatum(newval);
                        }
                        values[attindex - 1] = keyval;
-                       nulls[attindex - 1] = ' ';
+                       nulls[attindex - 1] = false;
                }
                else
                {
@@ -1712,7 +1680,7 @@ build_dummy_tuple(CatCache *cache, int nkeys, ScanKey skeys)
                }
        }
 
-       ntp = heap_formtuple(tupDesc, values, nulls);
+       ntp = heap_form_tuple(tupDesc, values, nulls);
        if (tupOid != InvalidOid)
                HeapTupleSetOid(ntp, tupOid);