1 /*-------------------------------------------------------------------------
4 * System cache management routines
6 * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/utils/cache/syscache.c
14 * These routines allow the parser/planner/executor to perform
15 * rapid lookups on the contents of the system catalogs.
17 * see utils/syscache.h for a list of the cache id's
19 *-------------------------------------------------------------------------
23 #include "access/sysattr.h"
24 #include "catalog/indexing.h"
25 #include "catalog/pg_aggregate.h"
26 #include "catalog/pg_amop.h"
27 #include "catalog/pg_amproc.h"
28 #include "catalog/pg_auth_members.h"
29 #include "catalog/pg_authid.h"
30 #include "catalog/pg_cast.h"
31 #include "catalog/pg_collation.h"
32 #include "catalog/pg_constraint.h"
33 #include "catalog/pg_conversion.h"
34 #include "catalog/pg_database.h"
35 #include "catalog/pg_default_acl.h"
36 #include "catalog/pg_enum.h"
37 #include "catalog/pg_foreign_data_wrapper.h"
38 #include "catalog/pg_foreign_server.h"
39 #include "catalog/pg_foreign_table.h"
40 #include "catalog/pg_language.h"
41 #include "catalog/pg_namespace.h"
42 #include "catalog/pg_opclass.h"
43 #include "catalog/pg_operator.h"
44 #include "catalog/pg_opfamily.h"
45 #include "catalog/pg_proc.h"
46 #include "catalog/pg_rewrite.h"
47 #include "catalog/pg_statistic.h"
48 #include "catalog/pg_tablespace.h"
49 #include "catalog/pg_ts_config.h"
50 #include "catalog/pg_ts_config_map.h"
51 #include "catalog/pg_ts_dict.h"
52 #include "catalog/pg_ts_parser.h"
53 #include "catalog/pg_ts_template.h"
54 #include "catalog/pg_type.h"
55 #include "catalog/pg_user_mapping.h"
56 #include "utils/rel.h"
57 #include "utils/syscache.h"
60 /*---------------------------------------------------------------------------
64 Add your new cache to the list in include/utils/syscache.h.
65 Keep the list sorted alphabetically.
67 Add your entry to the cacheinfo[] array below. All cache lists are
68 alphabetical, so add it in the proper place. Specify the relation OID,
69 index OID, number of keys, key attribute numbers, and initial number of
72 The number of hash buckets must be a power of 2. It's reasonable to
73 set this to the number of entries that might be in the particular cache
74 in a medium-size database.
76 There must be a unique index underlying each syscache (ie, an index
77 whose key is the same as that of the cache). If there is not one
78 already, add definitions for it to include/catalog/indexing.h: you need
79 to add a DECLARE_UNIQUE_INDEX macro and a #define for the index OID.
80 (Adding an index requires a catversion.h update, while simply
81 adding/deleting caches only requires a recompile.)
83 Finally, any place your relation gets heap_insert() or
84 heap_update() calls, make sure there is a CatalogUpdateIndexes() or
85 similar call. The heap_* calls do not update indexes.
89 *---------------------------------------------------------------------------
93 * struct cachedesc: information defining a single syscache
97 Oid reloid; /* OID of the relation being cached */
98 Oid indoid; /* OID of index relation for this cache */
99 int nkeys; /* # of keys needed for cache lookup */
100 int key[4]; /* attribute numbers of key attrs */
101 int nbuckets; /* number of hash buckets for this cache */
104 static const struct cachedesc cacheinfo[] = {
105 {AggregateRelationId, /* AGGFNOID */
106 AggregateFnoidIndexId,
109 Anum_pg_aggregate_aggfnoid,
116 {AccessMethodRelationId, /* AMNAME */
127 {AccessMethodRelationId, /* AMOID */
131 ObjectIdAttributeNumber,
138 {AccessMethodOperatorRelationId, /* AMOPOPID */
139 AccessMethodOperatorIndexId,
142 Anum_pg_amop_amopopr,
143 Anum_pg_amop_amoppurpose,
144 Anum_pg_amop_amopfamily,
149 {AccessMethodOperatorRelationId, /* AMOPSTRATEGY */
150 AccessMethodStrategyIndexId,
153 Anum_pg_amop_amopfamily,
154 Anum_pg_amop_amoplefttype,
155 Anum_pg_amop_amoprighttype,
156 Anum_pg_amop_amopstrategy
160 {AccessMethodProcedureRelationId, /* AMPROCNUM */
161 AccessMethodProcedureIndexId,
164 Anum_pg_amproc_amprocfamily,
165 Anum_pg_amproc_amproclefttype,
166 Anum_pg_amproc_amprocrighttype,
167 Anum_pg_amproc_amprocnum
171 {AttributeRelationId, /* ATTNAME */
172 AttributeRelidNameIndexId,
175 Anum_pg_attribute_attrelid,
176 Anum_pg_attribute_attname,
182 {AttributeRelationId, /* ATTNUM */
183 AttributeRelidNumIndexId,
186 Anum_pg_attribute_attrelid,
187 Anum_pg_attribute_attnum,
193 {AuthMemRelationId, /* AUTHMEMMEMROLE */
194 AuthMemMemRoleIndexId,
197 Anum_pg_auth_members_member,
198 Anum_pg_auth_members_roleid,
204 {AuthMemRelationId, /* AUTHMEMROLEMEM */
205 AuthMemRoleMemIndexId,
208 Anum_pg_auth_members_roleid,
209 Anum_pg_auth_members_member,
215 {AuthIdRelationId, /* AUTHNAME */
216 AuthIdRolnameIndexId,
219 Anum_pg_authid_rolname,
226 {AuthIdRelationId, /* AUTHOID */
230 ObjectIdAttributeNumber,
238 CastRelationId, /* CASTSOURCETARGET */
239 CastSourceTargetIndexId,
242 Anum_pg_cast_castsource,
243 Anum_pg_cast_casttarget,
249 {OperatorClassRelationId, /* CLAAMNAMENSP */
250 OpclassAmNameNspIndexId,
253 Anum_pg_opclass_opcmethod,
254 Anum_pg_opclass_opcname,
255 Anum_pg_opclass_opcnamespace,
260 {OperatorClassRelationId, /* CLAOID */
264 ObjectIdAttributeNumber,
271 {CollationRelationId, /* COLLNAMEENCNSP */
272 CollationNameEncNspIndexId,
275 Anum_pg_collation_collname,
276 Anum_pg_collation_collencoding,
277 Anum_pg_collation_collnamespace,
282 {CollationRelationId, /* COLLOID */
286 ObjectIdAttributeNumber,
293 {ConversionRelationId, /* CONDEFAULT */
294 ConversionDefaultIndexId,
297 Anum_pg_conversion_connamespace,
298 Anum_pg_conversion_conforencoding,
299 Anum_pg_conversion_contoencoding,
300 ObjectIdAttributeNumber,
304 {ConversionRelationId, /* CONNAMENSP */
305 ConversionNameNspIndexId,
308 Anum_pg_conversion_conname,
309 Anum_pg_conversion_connamespace,
315 {ConstraintRelationId, /* CONSTROID */
316 ConstraintOidIndexId,
319 ObjectIdAttributeNumber,
326 {ConversionRelationId, /* CONVOID */
327 ConversionOidIndexId,
330 ObjectIdAttributeNumber,
337 {DatabaseRelationId, /* DATABASEOID */
341 ObjectIdAttributeNumber,
348 {DefaultAclRelationId, /* DEFACLROLENSPOBJ */
349 DefaultAclRoleNspObjIndexId,
352 Anum_pg_default_acl_defaclrole,
353 Anum_pg_default_acl_defaclnamespace,
354 Anum_pg_default_acl_defaclobjtype,
359 {EnumRelationId, /* ENUMOID */
363 ObjectIdAttributeNumber,
370 {EnumRelationId, /* ENUMTYPOIDNAME */
371 EnumTypIdLabelIndexId,
374 Anum_pg_enum_enumtypid,
375 Anum_pg_enum_enumlabel,
381 {ForeignDataWrapperRelationId, /* FOREIGNDATAWRAPPERNAME */
382 ForeignDataWrapperNameIndexId,
385 Anum_pg_foreign_data_wrapper_fdwname,
392 {ForeignDataWrapperRelationId, /* FOREIGNDATAWRAPPEROID */
393 ForeignDataWrapperOidIndexId,
396 ObjectIdAttributeNumber,
403 {ForeignServerRelationId, /* FOREIGNSERVERNAME */
404 ForeignServerNameIndexId,
407 Anum_pg_foreign_server_srvname,
414 {ForeignServerRelationId, /* FOREIGNSERVEROID */
415 ForeignServerOidIndexId,
418 ObjectIdAttributeNumber,
425 {ForeignTableRelationId, /* FOREIGNTABLEREL */
426 ForeignTableRelidIndexId,
429 Anum_pg_foreign_table_ftrelid,
436 {IndexRelationId, /* INDEXRELID */
440 Anum_pg_index_indexrelid,
447 {LanguageRelationId, /* LANGNAME */
451 Anum_pg_language_lanname,
458 {LanguageRelationId, /* LANGOID */
462 ObjectIdAttributeNumber,
469 {NamespaceRelationId, /* NAMESPACENAME */
470 NamespaceNameIndexId,
473 Anum_pg_namespace_nspname,
480 {NamespaceRelationId, /* NAMESPACEOID */
484 ObjectIdAttributeNumber,
491 {OperatorRelationId, /* OPERNAMENSP */
492 OperatorNameNspIndexId,
495 Anum_pg_operator_oprname,
496 Anum_pg_operator_oprleft,
497 Anum_pg_operator_oprright,
498 Anum_pg_operator_oprnamespace
502 {OperatorRelationId, /* OPEROID */
506 ObjectIdAttributeNumber,
513 {OperatorFamilyRelationId, /* OPFAMILYAMNAMENSP */
514 OpfamilyAmNameNspIndexId,
517 Anum_pg_opfamily_opfmethod,
518 Anum_pg_opfamily_opfname,
519 Anum_pg_opfamily_opfnamespace,
524 {OperatorFamilyRelationId, /* OPFAMILYOID */
528 ObjectIdAttributeNumber,
535 {ProcedureRelationId, /* PROCNAMEARGSNSP */
536 ProcedureNameArgsNspIndexId,
539 Anum_pg_proc_proname,
540 Anum_pg_proc_proargtypes,
541 Anum_pg_proc_pronamespace,
546 {ProcedureRelationId, /* PROCOID */
550 ObjectIdAttributeNumber,
557 {RelationRelationId, /* RELNAMENSP */
561 Anum_pg_class_relname,
562 Anum_pg_class_relnamespace,
568 {RelationRelationId, /* RELOID */
572 ObjectIdAttributeNumber,
579 {RewriteRelationId, /* RULERELNAME */
580 RewriteRelRulenameIndexId,
583 Anum_pg_rewrite_ev_class,
584 Anum_pg_rewrite_rulename,
590 {StatisticRelationId, /* STATRELATTINH */
591 StatisticRelidAttnumInhIndexId,
594 Anum_pg_statistic_starelid,
595 Anum_pg_statistic_staattnum,
596 Anum_pg_statistic_stainherit,
601 {TableSpaceRelationId, /* TABLESPACEOID */
602 TablespaceOidIndexId,
605 ObjectIdAttributeNumber,
612 {TSConfigMapRelationId, /* TSCONFIGMAP */
616 Anum_pg_ts_config_map_mapcfg,
617 Anum_pg_ts_config_map_maptokentype,
618 Anum_pg_ts_config_map_mapseqno,
623 {TSConfigRelationId, /* TSCONFIGNAMENSP */
624 TSConfigNameNspIndexId,
627 Anum_pg_ts_config_cfgname,
628 Anum_pg_ts_config_cfgnamespace,
634 {TSConfigRelationId, /* TSCONFIGOID */
638 ObjectIdAttributeNumber,
645 {TSDictionaryRelationId, /* TSDICTNAMENSP */
646 TSDictionaryNameNspIndexId,
649 Anum_pg_ts_dict_dictname,
650 Anum_pg_ts_dict_dictnamespace,
656 {TSDictionaryRelationId, /* TSDICTOID */
657 TSDictionaryOidIndexId,
660 ObjectIdAttributeNumber,
667 {TSParserRelationId, /* TSPARSERNAMENSP */
668 TSParserNameNspIndexId,
671 Anum_pg_ts_parser_prsname,
672 Anum_pg_ts_parser_prsnamespace,
678 {TSParserRelationId, /* TSPARSEROID */
682 ObjectIdAttributeNumber,
689 {TSTemplateRelationId, /* TSTEMPLATENAMENSP */
690 TSTemplateNameNspIndexId,
693 Anum_pg_ts_template_tmplname,
694 Anum_pg_ts_template_tmplnamespace,
700 {TSTemplateRelationId, /* TSTEMPLATEOID */
701 TSTemplateOidIndexId,
704 ObjectIdAttributeNumber,
711 {TypeRelationId, /* TYPENAMENSP */
715 Anum_pg_type_typname,
716 Anum_pg_type_typnamespace,
722 {TypeRelationId, /* TYPEOID */
726 ObjectIdAttributeNumber,
733 {UserMappingRelationId, /* USERMAPPINGOID */
734 UserMappingOidIndexId,
737 ObjectIdAttributeNumber,
744 {UserMappingRelationId, /* USERMAPPINGUSERSERVER */
745 UserMappingUserServerIndexId,
748 Anum_pg_user_mapping_umuser,
749 Anum_pg_user_mapping_umserver,
757 static CatCache *SysCache[
758 lengthof(cacheinfo)];
759 static int SysCacheSize = lengthof(cacheinfo);
760 static bool CacheInitialized = false;
764 * InitCatalogCache - initialize the caches
766 * Note that no database access is done here; we only allocate memory
767 * and initialize the cache structure. Interrogation of the database
768 * to complete initialization of a cache happens upon first use
772 InitCatalogCache(void)
776 Assert(!CacheInitialized);
778 MemSet(SysCache, 0, sizeof(SysCache));
780 for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
782 SysCache[cacheId] = InitCatCache(cacheId,
783 cacheinfo[cacheId].reloid,
784 cacheinfo[cacheId].indoid,
785 cacheinfo[cacheId].nkeys,
786 cacheinfo[cacheId].key,
787 cacheinfo[cacheId].nbuckets);
788 if (!PointerIsValid(SysCache[cacheId]))
789 elog(ERROR, "could not initialize cache %u (%d)",
790 cacheinfo[cacheId].reloid, cacheId);
792 CacheInitialized = true;
797 * InitCatalogCachePhase2 - finish initializing the caches
799 * Finish initializing all the caches, including necessary database
802 * This is *not* essential; normally we allow syscaches to be initialized
803 * on first use. However, it is useful as a mechanism to preload the
804 * relcache with entries for the most-commonly-used system catalogs.
805 * Therefore, we invoke this routine when we need to write a new relcache
809 InitCatalogCachePhase2(void)
813 Assert(CacheInitialized);
815 for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
816 InitCatCachePhase2(SysCache[cacheId], true);
823 * A layer on top of SearchCatCache that does the initialization and
824 * key-setting for you.
826 * Returns the cache copy of the tuple if one is found, NULL if not.
827 * The tuple is the 'cache' copy and must NOT be modified!
829 * When the caller is done using the tuple, call ReleaseSysCache()
830 * to release the reference count grabbed by SearchSysCache(). If this
831 * is not done, the tuple will remain locked in cache until end of
832 * transaction, which is tolerable but not desirable.
834 * CAUTION: The tuple that is returned must NOT be freed by the caller!
837 SearchSysCache(int cacheId,
843 if (cacheId < 0 || cacheId >= SysCacheSize ||
844 !PointerIsValid(SysCache[cacheId]))
845 elog(ERROR, "invalid cache id: %d", cacheId);
847 return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
852 * Release previously grabbed reference count on a tuple
855 ReleaseSysCache(HeapTuple tuple)
857 ReleaseCatCache(tuple);
863 * A convenience routine that does SearchSysCache and (if successful)
864 * returns a modifiable copy of the syscache entry. The original
865 * syscache entry is released before returning. The caller should
866 * heap_freetuple() the result when done with it.
869 SearchSysCacheCopy(int cacheId,
878 tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
879 if (!HeapTupleIsValid(tuple))
881 newtuple = heap_copytuple(tuple);
882 ReleaseSysCache(tuple);
887 * SearchSysCacheExists
889 * A convenience routine that just probes to see if a tuple can be found.
890 * No lock is retained on the syscache entry.
893 SearchSysCacheExists(int cacheId,
901 tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
902 if (!HeapTupleIsValid(tuple))
904 ReleaseSysCache(tuple);
911 * A convenience routine that does SearchSysCache and returns the OID
912 * of the found tuple, or InvalidOid if no tuple could be found.
913 * No lock is retained on the syscache entry.
916 GetSysCacheOid(int cacheId,
925 tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
926 if (!HeapTupleIsValid(tuple))
928 result = HeapTupleGetOid(tuple);
929 ReleaseSysCache(tuple);
935 * SearchSysCacheAttName
937 * This routine is equivalent to SearchSysCache on the ATTNAME cache,
938 * except that it will return NULL if the found attribute is marked
939 * attisdropped. This is convenient for callers that want to act as
940 * though dropped attributes don't exist.
943 SearchSysCacheAttName(Oid relid, const char *attname)
947 tuple = SearchSysCache2(ATTNAME,
948 ObjectIdGetDatum(relid),
949 CStringGetDatum(attname));
950 if (!HeapTupleIsValid(tuple))
952 if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
954 ReleaseSysCache(tuple);
961 * SearchSysCacheCopyAttName
963 * As above, an attisdropped-aware version of SearchSysCacheCopy.
966 SearchSysCacheCopyAttName(Oid relid, const char *attname)
971 tuple = SearchSysCacheAttName(relid, attname);
972 if (!HeapTupleIsValid(tuple))
974 newtuple = heap_copytuple(tuple);
975 ReleaseSysCache(tuple);
980 * SearchSysCacheExistsAttName
982 * As above, an attisdropped-aware version of SearchSysCacheExists.
985 SearchSysCacheExistsAttName(Oid relid, const char *attname)
989 tuple = SearchSysCacheAttName(relid, attname);
990 if (!HeapTupleIsValid(tuple))
992 ReleaseSysCache(tuple);
1000 * Given a tuple previously fetched by SearchSysCache(),
1001 * extract a specific attribute.
1003 * This is equivalent to using heap_getattr() on a tuple fetched
1004 * from a non-cached relation. Usually, this is only used for attributes
1005 * that could be NULL or variable length; the fixed-size attributes in
1006 * a system table are accessed just by mapping the tuple onto the C struct
1007 * declarations from include/catalog/.
1009 * As with heap_getattr(), if the attribute is of a pass-by-reference type
1010 * then a pointer into the tuple data area is returned --- the caller must
1011 * not modify or pfree the datum!
1013 * Note: it is legal to use SysCacheGetAttr() with a cacheId referencing
1014 * a different cache for the same catalog the tuple was fetched from.
1017 SysCacheGetAttr(int cacheId, HeapTuple tup,
1018 AttrNumber attributeNumber,
1022 * We just need to get the TupleDesc out of the cache entry, and then we
1023 * can apply heap_getattr(). Normally the cache control data is already
1024 * valid (because the caller recently fetched the tuple via this same
1025 * cache), but there are cases where we have to initialize the cache here.
1027 if (cacheId < 0 || cacheId >= SysCacheSize ||
1028 !PointerIsValid(SysCache[cacheId]))
1029 elog(ERROR, "invalid cache id: %d", cacheId);
1030 if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
1032 InitCatCachePhase2(SysCache[cacheId], false);
1033 Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
1036 return heap_getattr(tup, attributeNumber,
1037 SysCache[cacheId]->cc_tupdesc,
1042 * List-search interface
1045 SearchSysCacheList(int cacheId, int nkeys,
1046 Datum key1, Datum key2, Datum key3, Datum key4)
1048 if (cacheId < 0 || cacheId >= SysCacheSize ||
1049 !PointerIsValid(SysCache[cacheId]))
1050 elog(ERROR, "invalid cache id: %d", cacheId);
1052 return SearchCatCacheList(SysCache[cacheId], nkeys,
1053 key1, key2, key3, key4);