Header And Logo

PostgreSQL
| The world's most advanced open source database.

syscache.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * syscache.c
00004  *    System cache management routines
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/backend/utils/cache/syscache.c
00012  *
00013  * NOTES
00014  *    These routines allow the parser/planner/executor to perform
00015  *    rapid lookups on the contents of the system catalogs.
00016  *
00017  *    see utils/syscache.h for a list of the cache IDs
00018  *
00019  *-------------------------------------------------------------------------
00020  */
00021 #include "postgres.h"
00022 
00023 #include "access/htup_details.h"
00024 #include "access/sysattr.h"
00025 #include "catalog/indexing.h"
00026 #include "catalog/pg_aggregate.h"
00027 #include "catalog/pg_amop.h"
00028 #include "catalog/pg_amproc.h"
00029 #include "catalog/pg_auth_members.h"
00030 #include "catalog/pg_authid.h"
00031 #include "catalog/pg_cast.h"
00032 #include "catalog/pg_collation.h"
00033 #include "catalog/pg_constraint.h"
00034 #include "catalog/pg_conversion.h"
00035 #include "catalog/pg_database.h"
00036 #include "catalog/pg_default_acl.h"
00037 #include "catalog/pg_enum.h"
00038 #include "catalog/pg_event_trigger.h"
00039 #include "catalog/pg_foreign_data_wrapper.h"
00040 #include "catalog/pg_foreign_server.h"
00041 #include "catalog/pg_foreign_table.h"
00042 #include "catalog/pg_language.h"
00043 #include "catalog/pg_namespace.h"
00044 #include "catalog/pg_opclass.h"
00045 #include "catalog/pg_operator.h"
00046 #include "catalog/pg_opfamily.h"
00047 #include "catalog/pg_proc.h"
00048 #include "catalog/pg_range.h"
00049 #include "catalog/pg_rewrite.h"
00050 #include "catalog/pg_statistic.h"
00051 #include "catalog/pg_tablespace.h"
00052 #include "catalog/pg_ts_config.h"
00053 #include "catalog/pg_ts_config_map.h"
00054 #include "catalog/pg_ts_dict.h"
00055 #include "catalog/pg_ts_parser.h"
00056 #include "catalog/pg_ts_template.h"
00057 #include "catalog/pg_type.h"
00058 #include "catalog/pg_user_mapping.h"
00059 #include "utils/rel.h"
00060 #include "utils/catcache.h"
00061 #include "utils/syscache.h"
00062 
00063 
00064 /*---------------------------------------------------------------------------
00065 
00066     Adding system caches:
00067 
00068     Add your new cache to the list in include/utils/syscache.h.
00069     Keep the list sorted alphabetically.
00070 
00071     Add your entry to the cacheinfo[] array below. All cache lists are
00072     alphabetical, so add it in the proper place.  Specify the relation OID,
00073     index OID, number of keys, key attribute numbers, and initial number of
00074     hash buckets.
00075 
00076     The number of hash buckets must be a power of 2.  It's reasonable to
00077     set this to the number of entries that might be in the particular cache
00078     in a medium-size database.
00079 
00080     There must be a unique index underlying each syscache (ie, an index
00081     whose key is the same as that of the cache).  If there is not one
00082     already, add definitions for it to include/catalog/indexing.h: you need
00083     to add a DECLARE_UNIQUE_INDEX macro and a #define for the index OID.
00084     (Adding an index requires a catversion.h update, while simply
00085     adding/deleting caches only requires a recompile.)
00086 
00087     Finally, any place your relation gets heap_insert() or
00088     heap_update() calls, make sure there is a CatalogUpdateIndexes() or
00089     similar call.  The heap_* calls do not update indexes.
00090 
00091     bjm 1999/11/22
00092 
00093 *---------------------------------------------------------------------------
00094 */
00095 
00096 /*
00097  *      struct cachedesc: information defining a single syscache
00098  */
00099 struct cachedesc
00100 {
00101     Oid         reloid;         /* OID of the relation being cached */
00102     Oid         indoid;         /* OID of index relation for this cache */
00103     int         nkeys;          /* # of keys needed for cache lookup */
00104     int         key[4];         /* attribute numbers of key attrs */
00105     int         nbuckets;       /* number of hash buckets for this cache */
00106 };
00107 
00108 static const struct cachedesc cacheinfo[] = {
00109     {AggregateRelationId,       /* AGGFNOID */
00110         AggregateFnoidIndexId,
00111         1,
00112         {
00113             Anum_pg_aggregate_aggfnoid,
00114             0,
00115             0,
00116             0
00117         },
00118         32
00119     },
00120     {AccessMethodRelationId,    /* AMNAME */
00121         AmNameIndexId,
00122         1,
00123         {
00124             Anum_pg_am_amname,
00125             0,
00126             0,
00127             0
00128         },
00129         4
00130     },
00131     {AccessMethodRelationId,    /* AMOID */
00132         AmOidIndexId,
00133         1,
00134         {
00135             ObjectIdAttributeNumber,
00136             0,
00137             0,
00138             0
00139         },
00140         4
00141     },
00142     {AccessMethodOperatorRelationId,    /* AMOPOPID */
00143         AccessMethodOperatorIndexId,
00144         3,
00145         {
00146             Anum_pg_amop_amopopr,
00147             Anum_pg_amop_amoppurpose,
00148             Anum_pg_amop_amopfamily,
00149             0
00150         },
00151         64
00152     },
00153     {AccessMethodOperatorRelationId,    /* AMOPSTRATEGY */
00154         AccessMethodStrategyIndexId,
00155         4,
00156         {
00157             Anum_pg_amop_amopfamily,
00158             Anum_pg_amop_amoplefttype,
00159             Anum_pg_amop_amoprighttype,
00160             Anum_pg_amop_amopstrategy
00161         },
00162         64
00163     },
00164     {AccessMethodProcedureRelationId,   /* AMPROCNUM */
00165         AccessMethodProcedureIndexId,
00166         4,
00167         {
00168             Anum_pg_amproc_amprocfamily,
00169             Anum_pg_amproc_amproclefttype,
00170             Anum_pg_amproc_amprocrighttype,
00171             Anum_pg_amproc_amprocnum
00172         },
00173         64
00174     },
00175     {AttributeRelationId,       /* ATTNAME */
00176         AttributeRelidNameIndexId,
00177         2,
00178         {
00179             Anum_pg_attribute_attrelid,
00180             Anum_pg_attribute_attname,
00181             0,
00182             0
00183         },
00184         2048
00185     },
00186     {AttributeRelationId,       /* ATTNUM */
00187         AttributeRelidNumIndexId,
00188         2,
00189         {
00190             Anum_pg_attribute_attrelid,
00191             Anum_pg_attribute_attnum,
00192             0,
00193             0
00194         },
00195         2048
00196     },
00197     {AuthMemRelationId,         /* AUTHMEMMEMROLE */
00198         AuthMemMemRoleIndexId,
00199         2,
00200         {
00201             Anum_pg_auth_members_member,
00202             Anum_pg_auth_members_roleid,
00203             0,
00204             0
00205         },
00206         128
00207     },
00208     {AuthMemRelationId,         /* AUTHMEMROLEMEM */
00209         AuthMemRoleMemIndexId,
00210         2,
00211         {
00212             Anum_pg_auth_members_roleid,
00213             Anum_pg_auth_members_member,
00214             0,
00215             0
00216         },
00217         128
00218     },
00219     {AuthIdRelationId,          /* AUTHNAME */
00220         AuthIdRolnameIndexId,
00221         1,
00222         {
00223             Anum_pg_authid_rolname,
00224             0,
00225             0,
00226             0
00227         },
00228         128
00229     },
00230     {AuthIdRelationId,          /* AUTHOID */
00231         AuthIdOidIndexId,
00232         1,
00233         {
00234             ObjectIdAttributeNumber,
00235             0,
00236             0,
00237             0
00238         },
00239         128
00240     },
00241     {
00242         CastRelationId,         /* CASTSOURCETARGET */
00243         CastSourceTargetIndexId,
00244         2,
00245         {
00246             Anum_pg_cast_castsource,
00247             Anum_pg_cast_casttarget,
00248             0,
00249             0
00250         },
00251         256
00252     },
00253     {OperatorClassRelationId,   /* CLAAMNAMENSP */
00254         OpclassAmNameNspIndexId,
00255         3,
00256         {
00257             Anum_pg_opclass_opcmethod,
00258             Anum_pg_opclass_opcname,
00259             Anum_pg_opclass_opcnamespace,
00260             0
00261         },
00262         64
00263     },
00264     {OperatorClassRelationId,   /* CLAOID */
00265         OpclassOidIndexId,
00266         1,
00267         {
00268             ObjectIdAttributeNumber,
00269             0,
00270             0,
00271             0
00272         },
00273         64
00274     },
00275     {CollationRelationId,       /* COLLNAMEENCNSP */
00276         CollationNameEncNspIndexId,
00277         3,
00278         {
00279             Anum_pg_collation_collname,
00280             Anum_pg_collation_collencoding,
00281             Anum_pg_collation_collnamespace,
00282             0
00283         },
00284         64
00285     },
00286     {CollationRelationId,       /* COLLOID */
00287         CollationOidIndexId,
00288         1,
00289         {
00290             ObjectIdAttributeNumber,
00291             0,
00292             0,
00293             0
00294         },
00295         64
00296     },
00297     {ConversionRelationId,      /* CONDEFAULT */
00298         ConversionDefaultIndexId,
00299         4,
00300         {
00301             Anum_pg_conversion_connamespace,
00302             Anum_pg_conversion_conforencoding,
00303             Anum_pg_conversion_contoencoding,
00304             ObjectIdAttributeNumber,
00305         },
00306         128
00307     },
00308     {ConversionRelationId,      /* CONNAMENSP */
00309         ConversionNameNspIndexId,
00310         2,
00311         {
00312             Anum_pg_conversion_conname,
00313             Anum_pg_conversion_connamespace,
00314             0,
00315             0
00316         },
00317         128
00318     },
00319     {ConstraintRelationId,      /* CONSTROID */
00320         ConstraintOidIndexId,
00321         1,
00322         {
00323             ObjectIdAttributeNumber,
00324             0,
00325             0,
00326             0
00327         },
00328         1024
00329     },
00330     {ConversionRelationId,      /* CONVOID */
00331         ConversionOidIndexId,
00332         1,
00333         {
00334             ObjectIdAttributeNumber,
00335             0,
00336             0,
00337             0
00338         },
00339         128
00340     },
00341     {DatabaseRelationId,        /* DATABASEOID */
00342         DatabaseOidIndexId,
00343         1,
00344         {
00345             ObjectIdAttributeNumber,
00346             0,
00347             0,
00348             0
00349         },
00350         4
00351     },
00352     {DefaultAclRelationId,      /* DEFACLROLENSPOBJ */
00353         DefaultAclRoleNspObjIndexId,
00354         3,
00355         {
00356             Anum_pg_default_acl_defaclrole,
00357             Anum_pg_default_acl_defaclnamespace,
00358             Anum_pg_default_acl_defaclobjtype,
00359             0
00360         },
00361         256
00362     },
00363     {EnumRelationId,            /* ENUMOID */
00364         EnumOidIndexId,
00365         1,
00366         {
00367             ObjectIdAttributeNumber,
00368             0,
00369             0,
00370             0
00371         },
00372         256
00373     },
00374     {EnumRelationId,            /* ENUMTYPOIDNAME */
00375         EnumTypIdLabelIndexId,
00376         2,
00377         {
00378             Anum_pg_enum_enumtypid,
00379             Anum_pg_enum_enumlabel,
00380             0,
00381             0
00382         },
00383         256
00384     },
00385     {EventTriggerRelationId,            /* EVENTTRIGGERNAME */
00386         EventTriggerNameIndexId,
00387         1,
00388         {
00389             Anum_pg_event_trigger_evtname,
00390             0,
00391             0,
00392             0
00393         },
00394         8
00395     },
00396     {EventTriggerRelationId,            /* EVENTTRIGGEROID */
00397         EventTriggerOidIndexId,
00398         1,
00399         {
00400             ObjectIdAttributeNumber,
00401             0,
00402             0,
00403             0
00404         },
00405         8
00406     },
00407     {ForeignDataWrapperRelationId,      /* FOREIGNDATAWRAPPERNAME */
00408         ForeignDataWrapperNameIndexId,
00409         1,
00410         {
00411             Anum_pg_foreign_data_wrapper_fdwname,
00412             0,
00413             0,
00414             0
00415         },
00416         8
00417     },
00418     {ForeignDataWrapperRelationId,      /* FOREIGNDATAWRAPPEROID */
00419         ForeignDataWrapperOidIndexId,
00420         1,
00421         {
00422             ObjectIdAttributeNumber,
00423             0,
00424             0,
00425             0
00426         },
00427         8
00428     },
00429     {ForeignServerRelationId,   /* FOREIGNSERVERNAME */
00430         ForeignServerNameIndexId,
00431         1,
00432         {
00433             Anum_pg_foreign_server_srvname,
00434             0,
00435             0,
00436             0
00437         },
00438         32
00439     },
00440     {ForeignServerRelationId,   /* FOREIGNSERVEROID */
00441         ForeignServerOidIndexId,
00442         1,
00443         {
00444             ObjectIdAttributeNumber,
00445             0,
00446             0,
00447             0
00448         },
00449         32
00450     },
00451     {ForeignTableRelationId,    /* FOREIGNTABLEREL */
00452         ForeignTableRelidIndexId,
00453         1,
00454         {
00455             Anum_pg_foreign_table_ftrelid,
00456             0,
00457             0,
00458             0
00459         },
00460         128
00461     },
00462     {IndexRelationId,           /* INDEXRELID */
00463         IndexRelidIndexId,
00464         1,
00465         {
00466             Anum_pg_index_indexrelid,
00467             0,
00468             0,
00469             0
00470         },
00471         1024
00472     },
00473     {LanguageRelationId,        /* LANGNAME */
00474         LanguageNameIndexId,
00475         1,
00476         {
00477             Anum_pg_language_lanname,
00478             0,
00479             0,
00480             0
00481         },
00482         4
00483     },
00484     {LanguageRelationId,        /* LANGOID */
00485         LanguageOidIndexId,
00486         1,
00487         {
00488             ObjectIdAttributeNumber,
00489             0,
00490             0,
00491             0
00492         },
00493         4
00494     },
00495     {NamespaceRelationId,       /* NAMESPACENAME */
00496         NamespaceNameIndexId,
00497         1,
00498         {
00499             Anum_pg_namespace_nspname,
00500             0,
00501             0,
00502             0
00503         },
00504         256
00505     },
00506     {NamespaceRelationId,       /* NAMESPACEOID */
00507         NamespaceOidIndexId,
00508         1,
00509         {
00510             ObjectIdAttributeNumber,
00511             0,
00512             0,
00513             0
00514         },
00515         256
00516     },
00517     {OperatorRelationId,        /* OPERNAMENSP */
00518         OperatorNameNspIndexId,
00519         4,
00520         {
00521             Anum_pg_operator_oprname,
00522             Anum_pg_operator_oprleft,
00523             Anum_pg_operator_oprright,
00524             Anum_pg_operator_oprnamespace
00525         },
00526         1024
00527     },
00528     {OperatorRelationId,        /* OPEROID */
00529         OperatorOidIndexId,
00530         1,
00531         {
00532             ObjectIdAttributeNumber,
00533             0,
00534             0,
00535             0
00536         },
00537         1024
00538     },
00539     {OperatorFamilyRelationId,  /* OPFAMILYAMNAMENSP */
00540         OpfamilyAmNameNspIndexId,
00541         3,
00542         {
00543             Anum_pg_opfamily_opfmethod,
00544             Anum_pg_opfamily_opfname,
00545             Anum_pg_opfamily_opfnamespace,
00546             0
00547         },
00548         64
00549     },
00550     {OperatorFamilyRelationId,  /* OPFAMILYOID */
00551         OpfamilyOidIndexId,
00552         1,
00553         {
00554             ObjectIdAttributeNumber,
00555             0,
00556             0,
00557             0
00558         },
00559         64
00560     },
00561     {ProcedureRelationId,       /* PROCNAMEARGSNSP */
00562         ProcedureNameArgsNspIndexId,
00563         3,
00564         {
00565             Anum_pg_proc_proname,
00566             Anum_pg_proc_proargtypes,
00567             Anum_pg_proc_pronamespace,
00568             0
00569         },
00570         2048
00571     },
00572     {ProcedureRelationId,       /* PROCOID */
00573         ProcedureOidIndexId,
00574         1,
00575         {
00576             ObjectIdAttributeNumber,
00577             0,
00578             0,
00579             0
00580         },
00581         2048
00582     },
00583     {RangeRelationId,           /* RANGETYPE */
00584         RangeTypidIndexId,
00585         1,
00586         {
00587             Anum_pg_range_rngtypid,
00588             0,
00589             0,
00590             0
00591         },
00592         64
00593     },
00594     {RelationRelationId,        /* RELNAMENSP */
00595         ClassNameNspIndexId,
00596         2,
00597         {
00598             Anum_pg_class_relname,
00599             Anum_pg_class_relnamespace,
00600             0,
00601             0
00602         },
00603         1024
00604     },
00605     {RelationRelationId,        /* RELOID */
00606         ClassOidIndexId,
00607         1,
00608         {
00609             ObjectIdAttributeNumber,
00610             0,
00611             0,
00612             0
00613         },
00614         1024
00615     },
00616     {RewriteRelationId,         /* RULERELNAME */
00617         RewriteRelRulenameIndexId,
00618         2,
00619         {
00620             Anum_pg_rewrite_ev_class,
00621             Anum_pg_rewrite_rulename,
00622             0,
00623             0
00624         },
00625         1024
00626     },
00627     {StatisticRelationId,       /* STATRELATTINH */
00628         StatisticRelidAttnumInhIndexId,
00629         3,
00630         {
00631             Anum_pg_statistic_starelid,
00632             Anum_pg_statistic_staattnum,
00633             Anum_pg_statistic_stainherit,
00634             0
00635         },
00636         1024
00637     },
00638     {TableSpaceRelationId,      /* TABLESPACEOID */
00639         TablespaceOidIndexId,
00640         1,
00641         {
00642             ObjectIdAttributeNumber,
00643             0,
00644             0,
00645             0,
00646         },
00647         16
00648     },
00649     {TSConfigMapRelationId,     /* TSCONFIGMAP */
00650         TSConfigMapIndexId,
00651         3,
00652         {
00653             Anum_pg_ts_config_map_mapcfg,
00654             Anum_pg_ts_config_map_maptokentype,
00655             Anum_pg_ts_config_map_mapseqno,
00656             0
00657         },
00658         4
00659     },
00660     {TSConfigRelationId,        /* TSCONFIGNAMENSP */
00661         TSConfigNameNspIndexId,
00662         2,
00663         {
00664             Anum_pg_ts_config_cfgname,
00665             Anum_pg_ts_config_cfgnamespace,
00666             0,
00667             0
00668         },
00669         16
00670     },
00671     {TSConfigRelationId,        /* TSCONFIGOID */
00672         TSConfigOidIndexId,
00673         1,
00674         {
00675             ObjectIdAttributeNumber,
00676             0,
00677             0,
00678             0
00679         },
00680         16
00681     },
00682     {TSDictionaryRelationId,    /* TSDICTNAMENSP */
00683         TSDictionaryNameNspIndexId,
00684         2,
00685         {
00686             Anum_pg_ts_dict_dictname,
00687             Anum_pg_ts_dict_dictnamespace,
00688             0,
00689             0
00690         },
00691         16
00692     },
00693     {TSDictionaryRelationId,    /* TSDICTOID */
00694         TSDictionaryOidIndexId,
00695         1,
00696         {
00697             ObjectIdAttributeNumber,
00698             0,
00699             0,
00700             0
00701         },
00702         16
00703     },
00704     {TSParserRelationId,        /* TSPARSERNAMENSP */
00705         TSParserNameNspIndexId,
00706         2,
00707         {
00708             Anum_pg_ts_parser_prsname,
00709             Anum_pg_ts_parser_prsnamespace,
00710             0,
00711             0
00712         },
00713         4
00714     },
00715     {TSParserRelationId,        /* TSPARSEROID */
00716         TSParserOidIndexId,
00717         1,
00718         {
00719             ObjectIdAttributeNumber,
00720             0,
00721             0,
00722             0
00723         },
00724         4
00725     },
00726     {TSTemplateRelationId,      /* TSTEMPLATENAMENSP */
00727         TSTemplateNameNspIndexId,
00728         2,
00729         {
00730             Anum_pg_ts_template_tmplname,
00731             Anum_pg_ts_template_tmplnamespace,
00732             0,
00733             0
00734         },
00735         16
00736     },
00737     {TSTemplateRelationId,      /* TSTEMPLATEOID */
00738         TSTemplateOidIndexId,
00739         1,
00740         {
00741             ObjectIdAttributeNumber,
00742             0,
00743             0,
00744             0
00745         },
00746         16
00747     },
00748     {TypeRelationId,            /* TYPENAMENSP */
00749         TypeNameNspIndexId,
00750         2,
00751         {
00752             Anum_pg_type_typname,
00753             Anum_pg_type_typnamespace,
00754             0,
00755             0
00756         },
00757         1024
00758     },
00759     {TypeRelationId,            /* TYPEOID */
00760         TypeOidIndexId,
00761         1,
00762         {
00763             ObjectIdAttributeNumber,
00764             0,
00765             0,
00766             0
00767         },
00768         1024
00769     },
00770     {UserMappingRelationId,     /* USERMAPPINGOID */
00771         UserMappingOidIndexId,
00772         1,
00773         {
00774             ObjectIdAttributeNumber,
00775             0,
00776             0,
00777             0
00778         },
00779         128
00780     },
00781     {UserMappingRelationId,     /* USERMAPPINGUSERSERVER */
00782         UserMappingUserServerIndexId,
00783         2,
00784         {
00785             Anum_pg_user_mapping_umuser,
00786             Anum_pg_user_mapping_umserver,
00787             0,
00788             0
00789         },
00790         128
00791     }
00792 };
00793 
00794 static CatCache *SysCache[
00795                           lengthof(cacheinfo)];
00796 static int  SysCacheSize = lengthof(cacheinfo);
00797 static bool CacheInitialized = false;
00798 
00799 
00800 /*
00801  * InitCatalogCache - initialize the caches
00802  *
00803  * Note that no database access is done here; we only allocate memory
00804  * and initialize the cache structure.  Interrogation of the database
00805  * to complete initialization of a cache happens upon first use
00806  * of that cache.
00807  */
00808 void
00809 InitCatalogCache(void)
00810 {
00811     int         cacheId;
00812 
00813     Assert(!CacheInitialized);
00814 
00815     MemSet(SysCache, 0, sizeof(SysCache));
00816 
00817     for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
00818     {
00819         SysCache[cacheId] = InitCatCache(cacheId,
00820                                          cacheinfo[cacheId].reloid,
00821                                          cacheinfo[cacheId].indoid,
00822                                          cacheinfo[cacheId].nkeys,
00823                                          cacheinfo[cacheId].key,
00824                                          cacheinfo[cacheId].nbuckets);
00825         if (!PointerIsValid(SysCache[cacheId]))
00826             elog(ERROR, "could not initialize cache %u (%d)",
00827                  cacheinfo[cacheId].reloid, cacheId);
00828     }
00829     CacheInitialized = true;
00830 }
00831 
00832 
00833 /*
00834  * InitCatalogCachePhase2 - finish initializing the caches
00835  *
00836  * Finish initializing all the caches, including necessary database
00837  * access.
00838  *
00839  * This is *not* essential; normally we allow syscaches to be initialized
00840  * on first use.  However, it is useful as a mechanism to preload the
00841  * relcache with entries for the most-commonly-used system catalogs.
00842  * Therefore, we invoke this routine when we need to write a new relcache
00843  * init file.
00844  */
00845 void
00846 InitCatalogCachePhase2(void)
00847 {
00848     int         cacheId;
00849 
00850     Assert(CacheInitialized);
00851 
00852     for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
00853         InitCatCachePhase2(SysCache[cacheId], true);
00854 }
00855 
00856 
00857 /*
00858  * SearchSysCache
00859  *
00860  *  A layer on top of SearchCatCache that does the initialization and
00861  *  key-setting for you.
00862  *
00863  *  Returns the cache copy of the tuple if one is found, NULL if not.
00864  *  The tuple is the 'cache' copy and must NOT be modified!
00865  *
00866  *  When the caller is done using the tuple, call ReleaseSysCache()
00867  *  to release the reference count grabbed by SearchSysCache().  If this
00868  *  is not done, the tuple will remain locked in cache until end of
00869  *  transaction, which is tolerable but not desirable.
00870  *
00871  *  CAUTION: The tuple that is returned must NOT be freed by the caller!
00872  */
00873 HeapTuple
00874 SearchSysCache(int cacheId,
00875                Datum key1,
00876                Datum key2,
00877                Datum key3,
00878                Datum key4)
00879 {
00880     if (cacheId < 0 || cacheId >= SysCacheSize ||
00881         !PointerIsValid(SysCache[cacheId]))
00882         elog(ERROR, "invalid cache ID: %d", cacheId);
00883 
00884     return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
00885 }
00886 
00887 /*
00888  * ReleaseSysCache
00889  *      Release previously grabbed reference count on a tuple
00890  */
00891 void
00892 ReleaseSysCache(HeapTuple tuple)
00893 {
00894     ReleaseCatCache(tuple);
00895 }
00896 
00897 /*
00898  * SearchSysCacheCopy
00899  *
00900  * A convenience routine that does SearchSysCache and (if successful)
00901  * returns a modifiable copy of the syscache entry.  The original
00902  * syscache entry is released before returning.  The caller should
00903  * heap_freetuple() the result when done with it.
00904  */
00905 HeapTuple
00906 SearchSysCacheCopy(int cacheId,
00907                    Datum key1,
00908                    Datum key2,
00909                    Datum key3,
00910                    Datum key4)
00911 {
00912     HeapTuple   tuple,
00913                 newtuple;
00914 
00915     tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
00916     if (!HeapTupleIsValid(tuple))
00917         return tuple;
00918     newtuple = heap_copytuple(tuple);
00919     ReleaseSysCache(tuple);
00920     return newtuple;
00921 }
00922 
00923 /*
00924  * SearchSysCacheExists
00925  *
00926  * A convenience routine that just probes to see if a tuple can be found.
00927  * No lock is retained on the syscache entry.
00928  */
00929 bool
00930 SearchSysCacheExists(int cacheId,
00931                      Datum key1,
00932                      Datum key2,
00933                      Datum key3,
00934                      Datum key4)
00935 {
00936     HeapTuple   tuple;
00937 
00938     tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
00939     if (!HeapTupleIsValid(tuple))
00940         return false;
00941     ReleaseSysCache(tuple);
00942     return true;
00943 }
00944 
00945 /*
00946  * GetSysCacheOid
00947  *
00948  * A convenience routine that does SearchSysCache and returns the OID
00949  * of the found tuple, or InvalidOid if no tuple could be found.
00950  * No lock is retained on the syscache entry.
00951  */
00952 Oid
00953 GetSysCacheOid(int cacheId,
00954                Datum key1,
00955                Datum key2,
00956                Datum key3,
00957                Datum key4)
00958 {
00959     HeapTuple   tuple;
00960     Oid         result;
00961 
00962     tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
00963     if (!HeapTupleIsValid(tuple))
00964         return InvalidOid;
00965     result = HeapTupleGetOid(tuple);
00966     ReleaseSysCache(tuple);
00967     return result;
00968 }
00969 
00970 
00971 /*
00972  * SearchSysCacheAttName
00973  *
00974  * This routine is equivalent to SearchSysCache on the ATTNAME cache,
00975  * except that it will return NULL if the found attribute is marked
00976  * attisdropped.  This is convenient for callers that want to act as
00977  * though dropped attributes don't exist.
00978  */
00979 HeapTuple
00980 SearchSysCacheAttName(Oid relid, const char *attname)
00981 {
00982     HeapTuple   tuple;
00983 
00984     tuple = SearchSysCache2(ATTNAME,
00985                             ObjectIdGetDatum(relid),
00986                             CStringGetDatum(attname));
00987     if (!HeapTupleIsValid(tuple))
00988         return NULL;
00989     if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
00990     {
00991         ReleaseSysCache(tuple);
00992         return NULL;
00993     }
00994     return tuple;
00995 }
00996 
00997 /*
00998  * SearchSysCacheCopyAttName
00999  *
01000  * As above, an attisdropped-aware version of SearchSysCacheCopy.
01001  */
01002 HeapTuple
01003 SearchSysCacheCopyAttName(Oid relid, const char *attname)
01004 {
01005     HeapTuple   tuple,
01006                 newtuple;
01007 
01008     tuple = SearchSysCacheAttName(relid, attname);
01009     if (!HeapTupleIsValid(tuple))
01010         return tuple;
01011     newtuple = heap_copytuple(tuple);
01012     ReleaseSysCache(tuple);
01013     return newtuple;
01014 }
01015 
01016 /*
01017  * SearchSysCacheExistsAttName
01018  *
01019  * As above, an attisdropped-aware version of SearchSysCacheExists.
01020  */
01021 bool
01022 SearchSysCacheExistsAttName(Oid relid, const char *attname)
01023 {
01024     HeapTuple   tuple;
01025 
01026     tuple = SearchSysCacheAttName(relid, attname);
01027     if (!HeapTupleIsValid(tuple))
01028         return false;
01029     ReleaseSysCache(tuple);
01030     return true;
01031 }
01032 
01033 
01034 /*
01035  * SysCacheGetAttr
01036  *
01037  *      Given a tuple previously fetched by SearchSysCache(),
01038  *      extract a specific attribute.
01039  *
01040  * This is equivalent to using heap_getattr() on a tuple fetched
01041  * from a non-cached relation.  Usually, this is only used for attributes
01042  * that could be NULL or variable length; the fixed-size attributes in
01043  * a system table are accessed just by mapping the tuple onto the C struct
01044  * declarations from include/catalog/.
01045  *
01046  * As with heap_getattr(), if the attribute is of a pass-by-reference type
01047  * then a pointer into the tuple data area is returned --- the caller must
01048  * not modify or pfree the datum!
01049  *
01050  * Note: it is legal to use SysCacheGetAttr() with a cacheId referencing
01051  * a different cache for the same catalog the tuple was fetched from.
01052  */
01053 Datum
01054 SysCacheGetAttr(int cacheId, HeapTuple tup,
01055                 AttrNumber attributeNumber,
01056                 bool *isNull)
01057 {
01058     /*
01059      * We just need to get the TupleDesc out of the cache entry, and then we
01060      * can apply heap_getattr().  Normally the cache control data is already
01061      * valid (because the caller recently fetched the tuple via this same
01062      * cache), but there are cases where we have to initialize the cache here.
01063      */
01064     if (cacheId < 0 || cacheId >= SysCacheSize ||
01065         !PointerIsValid(SysCache[cacheId]))
01066         elog(ERROR, "invalid cache ID: %d", cacheId);
01067     if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
01068     {
01069         InitCatCachePhase2(SysCache[cacheId], false);
01070         Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
01071     }
01072 
01073     return heap_getattr(tup, attributeNumber,
01074                         SysCache[cacheId]->cc_tupdesc,
01075                         isNull);
01076 }
01077 
01078 /*
01079  * GetSysCacheHashValue
01080  *
01081  * Get the hash value that would be used for a tuple in the specified cache
01082  * with the given search keys.
01083  *
01084  * The reason for exposing this as part of the API is that the hash value is
01085  * exposed in cache invalidation operations, so there are places outside the
01086  * catcache code that need to be able to compute the hash values.
01087  */
01088 uint32
01089 GetSysCacheHashValue(int cacheId,
01090                      Datum key1,
01091                      Datum key2,
01092                      Datum key3,
01093                      Datum key4)
01094 {
01095     if (cacheId < 0 || cacheId >= SysCacheSize ||
01096         !PointerIsValid(SysCache[cacheId]))
01097         elog(ERROR, "invalid cache ID: %d", cacheId);
01098 
01099     return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
01100 }
01101 
01102 /*
01103  * List-search interface
01104  */
01105 struct catclist *
01106 SearchSysCacheList(int cacheId, int nkeys,
01107                    Datum key1, Datum key2, Datum key3, Datum key4)
01108 {
01109     if (cacheId < 0 || cacheId >= SysCacheSize ||
01110         !PointerIsValid(SysCache[cacheId]))
01111         elog(ERROR, "invalid cache ID: %d", cacheId);
01112 
01113     return SearchCatCacheList(SysCache[cacheId], nkeys,
01114                               key1, key2, key3, key4);
01115 }