1 /*-------------------------------------------------------------------------
4 * System cache management routines
6 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
14 * These routines allow the parser/planner/executor to perform
15 * rapid lookups on the contents of the system catalogs.
17 * see catalog/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_constraint.h"
32 #include "catalog/pg_conversion.h"
33 #include "catalog/pg_database.h"
34 #include "catalog/pg_enum.h"
35 #include "catalog/pg_foreign_data_wrapper.h"
36 #include "catalog/pg_foreign_server.h"
37 #include "catalog/pg_language.h"
38 #include "catalog/pg_namespace.h"
39 #include "catalog/pg_opclass.h"
40 #include "catalog/pg_operator.h"
41 #include "catalog/pg_opfamily.h"
42 #include "catalog/pg_proc.h"
43 #include "catalog/pg_rewrite.h"
44 #include "catalog/pg_statistic.h"
45 #include "catalog/pg_ts_config.h"
46 #include "catalog/pg_ts_config_map.h"
47 #include "catalog/pg_ts_dict.h"
48 #include "catalog/pg_ts_parser.h"
49 #include "catalog/pg_ts_template.h"
50 #include "catalog/pg_type.h"
51 #include "catalog/pg_user_mapping.h"
52 #include "utils/rel.h"
53 #include "utils/syscache.h"
56 /*---------------------------------------------------------------------------
60 Add your new cache to the list in include/utils/syscache.h.
61 Keep the list sorted alphabetically.
63 Add your entry to the cacheinfo[] array below. All cache lists are
64 alphabetical, so add it in the proper place. Specify the relation OID,
65 index OID, number of keys, key attribute numbers, and number of hash
66 buckets. If the relation contains tuples that are associated with a
67 particular relation (for example, its attributes, rules, triggers, etc)
68 then specify the attribute number that contains the OID of the associated
69 relation. This is used by CatalogCacheFlushRelation() to remove the
70 correct tuples during a table drop or relcache invalidation event.
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 reloidattr
; /* attr number of rel OID reference, or 0 */
100 int nkeys
; /* # of keys needed for cache lookup */
101 int key
[4]; /* attribute numbers of key attrs */
102 int nbuckets
; /* number of hash buckets for this cache */
105 static const struct cachedesc cacheinfo
[] = {
106 {AggregateRelationId
, /* AGGFNOID */
107 AggregateFnoidIndexId
,
111 Anum_pg_aggregate_aggfnoid
,
118 {AccessMethodRelationId
, /* AMNAME */
130 {AccessMethodRelationId
, /* AMOID */
135 ObjectIdAttributeNumber
,
142 {AccessMethodOperatorRelationId
, /* AMOPOPID */
143 AccessMethodOperatorIndexId
,
147 Anum_pg_amop_amopopr
,
148 Anum_pg_amop_amopfamily
,
154 {AccessMethodOperatorRelationId
, /* AMOPSTRATEGY */
155 AccessMethodStrategyIndexId
,
159 Anum_pg_amop_amopfamily
,
160 Anum_pg_amop_amoplefttype
,
161 Anum_pg_amop_amoprighttype
,
162 Anum_pg_amop_amopstrategy
166 {AccessMethodProcedureRelationId
, /* AMPROCNUM */
167 AccessMethodProcedureIndexId
,
171 Anum_pg_amproc_amprocfamily
,
172 Anum_pg_amproc_amproclefttype
,
173 Anum_pg_amproc_amprocrighttype
,
174 Anum_pg_amproc_amprocnum
178 {AttributeRelationId
, /* ATTNAME */
179 AttributeRelidNameIndexId
,
180 Anum_pg_attribute_attrelid
,
183 Anum_pg_attribute_attrelid
,
184 Anum_pg_attribute_attname
,
190 {AttributeRelationId
, /* ATTNUM */
191 AttributeRelidNumIndexId
,
192 Anum_pg_attribute_attrelid
,
195 Anum_pg_attribute_attrelid
,
196 Anum_pg_attribute_attnum
,
202 {AuthMemRelationId
, /* AUTHMEMMEMROLE */
203 AuthMemMemRoleIndexId
,
207 Anum_pg_auth_members_member
,
208 Anum_pg_auth_members_roleid
,
214 {AuthMemRelationId
, /* AUTHMEMROLEMEM */
215 AuthMemRoleMemIndexId
,
219 Anum_pg_auth_members_roleid
,
220 Anum_pg_auth_members_member
,
226 {AuthIdRelationId
, /* AUTHNAME */
227 AuthIdRolnameIndexId
,
231 Anum_pg_authid_rolname
,
238 {AuthIdRelationId
, /* AUTHOID */
243 ObjectIdAttributeNumber
,
251 CastRelationId
, /* CASTSOURCETARGET */
252 CastSourceTargetIndexId
,
256 Anum_pg_cast_castsource
,
257 Anum_pg_cast_casttarget
,
263 {OperatorClassRelationId
, /* CLAAMNAMENSP */
264 OpclassAmNameNspIndexId
,
268 Anum_pg_opclass_opcmethod
,
269 Anum_pg_opclass_opcname
,
270 Anum_pg_opclass_opcnamespace
,
275 {OperatorClassRelationId
, /* CLAOID */
280 ObjectIdAttributeNumber
,
287 {ConversionRelationId
, /* CONDEFAULT */
288 ConversionDefaultIndexId
,
292 Anum_pg_conversion_connamespace
,
293 Anum_pg_conversion_conforencoding
,
294 Anum_pg_conversion_contoencoding
,
295 ObjectIdAttributeNumber
,
299 {ConversionRelationId
, /* CONNAMENSP */
300 ConversionNameNspIndexId
,
304 Anum_pg_conversion_conname
,
305 Anum_pg_conversion_connamespace
,
311 {ConstraintRelationId
, /* CONSTROID */
312 ConstraintOidIndexId
,
313 Anum_pg_constraint_conrelid
,
316 ObjectIdAttributeNumber
,
323 {ConversionRelationId
, /* CONVOID */
324 ConversionOidIndexId
,
328 ObjectIdAttributeNumber
,
335 {DatabaseRelationId
, /* DATABASEOID */
340 ObjectIdAttributeNumber
,
347 {EnumRelationId
, /* ENUMOID */
352 ObjectIdAttributeNumber
,
359 {EnumRelationId
, /* ENUMTYPOIDNAME */
360 EnumTypIdLabelIndexId
,
364 Anum_pg_enum_enumtypid
,
365 Anum_pg_enum_enumlabel
,
371 {ForeignDataWrapperRelationId
, /* FOREIGNDATAWRAPPERNAME */
372 ForeignDataWrapperNameIndexId
,
376 Anum_pg_foreign_data_wrapper_fdwname
,
383 {ForeignDataWrapperRelationId
, /* FOREIGNDATAWRAPPEROID */
384 ForeignDataWrapperOidIndexId
,
388 ObjectIdAttributeNumber
,
395 {ForeignServerRelationId
, /* FOREIGNSERVERNAME */
396 ForeignServerNameIndexId
,
400 Anum_pg_foreign_server_srvname
,
407 {ForeignServerRelationId
, /* FOREIGNSERVEROID */
408 ForeignServerOidIndexId
,
412 ObjectIdAttributeNumber
,
419 {IndexRelationId
, /* INDEXRELID */
421 Anum_pg_index_indrelid
,
424 Anum_pg_index_indexrelid
,
431 {LanguageRelationId
, /* LANGNAME */
436 Anum_pg_language_lanname
,
443 {LanguageRelationId
, /* LANGOID */
448 ObjectIdAttributeNumber
,
455 {NamespaceRelationId
, /* NAMESPACENAME */
456 NamespaceNameIndexId
,
460 Anum_pg_namespace_nspname
,
467 {NamespaceRelationId
, /* NAMESPACEOID */
472 ObjectIdAttributeNumber
,
479 {OperatorRelationId
, /* OPERNAMENSP */
480 OperatorNameNspIndexId
,
484 Anum_pg_operator_oprname
,
485 Anum_pg_operator_oprleft
,
486 Anum_pg_operator_oprright
,
487 Anum_pg_operator_oprnamespace
491 {OperatorRelationId
, /* OPEROID */
496 ObjectIdAttributeNumber
,
503 {OperatorFamilyRelationId
, /* OPFAMILYAMNAMENSP */
504 OpfamilyAmNameNspIndexId
,
508 Anum_pg_opfamily_opfmethod
,
509 Anum_pg_opfamily_opfname
,
510 Anum_pg_opfamily_opfnamespace
,
515 {OperatorFamilyRelationId
, /* OPFAMILYOID */
520 ObjectIdAttributeNumber
,
527 {ProcedureRelationId
, /* PROCNAMEARGSNSP */
528 ProcedureNameArgsNspIndexId
,
532 Anum_pg_proc_proname
,
533 Anum_pg_proc_proargtypes
,
534 Anum_pg_proc_pronamespace
,
539 {ProcedureRelationId
, /* PROCOID */
544 ObjectIdAttributeNumber
,
551 {RelationRelationId
, /* RELNAMENSP */
553 ObjectIdAttributeNumber
,
556 Anum_pg_class_relname
,
557 Anum_pg_class_relnamespace
,
563 {RelationRelationId
, /* RELOID */
565 ObjectIdAttributeNumber
,
568 ObjectIdAttributeNumber
,
575 {RewriteRelationId
, /* RULERELNAME */
576 RewriteRelRulenameIndexId
,
577 Anum_pg_rewrite_ev_class
,
580 Anum_pg_rewrite_ev_class
,
581 Anum_pg_rewrite_rulename
,
587 {StatisticRelationId
, /* STATRELATT */
588 StatisticRelidAttnumIndexId
,
589 Anum_pg_statistic_starelid
,
592 Anum_pg_statistic_starelid
,
593 Anum_pg_statistic_staattnum
,
599 {TSConfigMapRelationId
, /* TSCONFIGMAP */
604 Anum_pg_ts_config_map_mapcfg
,
605 Anum_pg_ts_config_map_maptokentype
,
606 Anum_pg_ts_config_map_mapseqno
,
611 {TSConfigRelationId
, /* TSCONFIGNAMENSP */
612 TSConfigNameNspIndexId
,
616 Anum_pg_ts_config_cfgname
,
617 Anum_pg_ts_config_cfgnamespace
,
623 {TSConfigRelationId
, /* TSCONFIGOID */
628 ObjectIdAttributeNumber
,
635 {TSDictionaryRelationId
, /* TSDICTNAMENSP */
636 TSDictionaryNameNspIndexId
,
640 Anum_pg_ts_dict_dictname
,
641 Anum_pg_ts_dict_dictnamespace
,
647 {TSDictionaryRelationId
, /* TSDICTOID */
648 TSDictionaryOidIndexId
,
652 ObjectIdAttributeNumber
,
659 {TSParserRelationId
, /* TSPARSERNAMENSP */
660 TSParserNameNspIndexId
,
664 Anum_pg_ts_parser_prsname
,
665 Anum_pg_ts_parser_prsnamespace
,
671 {TSParserRelationId
, /* TSPARSEROID */
676 ObjectIdAttributeNumber
,
683 {TSTemplateRelationId
, /* TSTEMPLATENAMENSP */
684 TSTemplateNameNspIndexId
,
688 Anum_pg_ts_template_tmplname
,
689 Anum_pg_ts_template_tmplnamespace
,
695 {TSTemplateRelationId
, /* TSTEMPLATEOID */
696 TSTemplateOidIndexId
,
700 ObjectIdAttributeNumber
,
707 {TypeRelationId
, /* TYPENAMENSP */
709 Anum_pg_type_typrelid
,
712 Anum_pg_type_typname
,
713 Anum_pg_type_typnamespace
,
719 {TypeRelationId
, /* TYPEOID */
721 Anum_pg_type_typrelid
,
724 ObjectIdAttributeNumber
,
731 {UserMappingRelationId
, /* USERMAPPINGOID */
732 UserMappingOidIndexId
,
736 ObjectIdAttributeNumber
,
743 {UserMappingRelationId
, /* USERMAPPINGUSERSERVER */
744 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
].reloidattr
,
786 cacheinfo
[cacheId
].nkeys
,
787 cacheinfo
[cacheId
].key
,
788 cacheinfo
[cacheId
].nbuckets
);
789 if (!PointerIsValid(SysCache
[cacheId
]))
790 elog(ERROR
, "could not initialize cache %u (%d)",
791 cacheinfo
[cacheId
].reloid
, cacheId
);
793 CacheInitialized
= true;
798 * InitCatalogCachePhase2 - finish initializing the caches
800 * Finish initializing all the caches, including necessary database
803 * This is *not* essential; normally we allow syscaches to be initialized
804 * on first use. However, it is useful as a mechanism to preload the
805 * relcache with entries for the most-commonly-used system catalogs.
806 * Therefore, we invoke this routine when we need to write a new relcache
810 InitCatalogCachePhase2(void)
814 Assert(CacheInitialized
);
816 for (cacheId
= 0; cacheId
< SysCacheSize
; cacheId
++)
817 InitCatCachePhase2(SysCache
[cacheId
], true);
824 * A layer on top of SearchCatCache that does the initialization and
825 * key-setting for you.
827 * Returns the cache copy of the tuple if one is found, NULL if not.
828 * The tuple is the 'cache' copy and must NOT be modified!
830 * When the caller is done using the tuple, call ReleaseSysCache()
831 * to release the reference count grabbed by SearchSysCache(). If this
832 * is not done, the tuple will remain locked in cache until end of
833 * transaction, which is tolerable but not desirable.
835 * CAUTION: The tuple that is returned must NOT be freed by the caller!
838 SearchSysCache(int cacheId
,
844 if (cacheId
< 0 || cacheId
>= SysCacheSize
||
845 !PointerIsValid(SysCache
[cacheId
]))
846 elog(ERROR
, "invalid cache id: %d", cacheId
);
848 return SearchCatCache(SysCache
[cacheId
], key1
, key2
, key3
, key4
);
853 * Release previously grabbed reference count on a tuple
856 ReleaseSysCache(HeapTuple tuple
)
858 ReleaseCatCache(tuple
);
864 * A convenience routine that does SearchSysCache and (if successful)
865 * returns a modifiable copy of the syscache entry. The original
866 * syscache entry is released before returning. The caller should
867 * heap_freetuple() the result when done with it.
870 SearchSysCacheCopy(int cacheId
,
879 tuple
= SearchSysCache(cacheId
, key1
, key2
, key3
, key4
);
880 if (!HeapTupleIsValid(tuple
))
882 newtuple
= heap_copytuple(tuple
);
883 ReleaseSysCache(tuple
);
888 * SearchSysCacheExists
890 * A convenience routine that just probes to see if a tuple can be found.
891 * No lock is retained on the syscache entry.
894 SearchSysCacheExists(int cacheId
,
902 tuple
= SearchSysCache(cacheId
, key1
, key2
, key3
, key4
);
903 if (!HeapTupleIsValid(tuple
))
905 ReleaseSysCache(tuple
);
912 * A convenience routine that does SearchSysCache and returns the OID
913 * of the found tuple, or InvalidOid if no tuple could be found.
914 * No lock is retained on the syscache entry.
917 GetSysCacheOid(int cacheId
,
926 tuple
= SearchSysCache(cacheId
, key1
, key2
, key3
, key4
);
927 if (!HeapTupleIsValid(tuple
))
929 result
= HeapTupleGetOid(tuple
);
930 ReleaseSysCache(tuple
);
936 * SearchSysCacheAttName
938 * This routine is equivalent to SearchSysCache on the ATTNAME cache,
939 * except that it will return NULL if the found attribute is marked
940 * attisdropped. This is convenient for callers that want to act as
941 * though dropped attributes don't exist.
944 SearchSysCacheAttName(Oid relid
, const char *attname
)
948 tuple
= SearchSysCache(ATTNAME
,
949 ObjectIdGetDatum(relid
),
950 CStringGetDatum(attname
),
952 if (!HeapTupleIsValid(tuple
))
954 if (((Form_pg_attribute
) GETSTRUCT(tuple
))->attisdropped
)
956 ReleaseSysCache(tuple
);
963 * SearchSysCacheCopyAttName
965 * As above, an attisdropped-aware version of SearchSysCacheCopy.
968 SearchSysCacheCopyAttName(Oid relid
, const char *attname
)
973 tuple
= SearchSysCacheAttName(relid
, attname
);
974 if (!HeapTupleIsValid(tuple
))
976 newtuple
= heap_copytuple(tuple
);
977 ReleaseSysCache(tuple
);
982 * SearchSysCacheExistsAttName
984 * As above, an attisdropped-aware version of SearchSysCacheExists.
987 SearchSysCacheExistsAttName(Oid relid
, const char *attname
)
991 tuple
= SearchSysCacheAttName(relid
, attname
);
992 if (!HeapTupleIsValid(tuple
))
994 ReleaseSysCache(tuple
);
1002 * Given a tuple previously fetched by SearchSysCache(),
1003 * extract a specific attribute.
1005 * This is equivalent to using heap_getattr() on a tuple fetched
1006 * from a non-cached relation. Usually, this is only used for attributes
1007 * that could be NULL or variable length; the fixed-size attributes in
1008 * a system table are accessed just by mapping the tuple onto the C struct
1009 * declarations from include/catalog/.
1011 * As with heap_getattr(), if the attribute is of a pass-by-reference type
1012 * then a pointer into the tuple data area is returned --- the caller must
1013 * not modify or pfree the datum!
1015 * Note: it is legal to use SysCacheGetAttr() with a cacheId referencing
1016 * a different cache for the same catalog the tuple was fetched from.
1019 SysCacheGetAttr(int cacheId
, HeapTuple tup
,
1020 AttrNumber attributeNumber
,
1024 * We just need to get the TupleDesc out of the cache entry, and then we
1025 * can apply heap_getattr(). Normally the cache control data is already
1026 * valid (because the caller recently fetched the tuple via this same
1027 * cache), but there are cases where we have to initialize the cache here.
1029 if (cacheId
< 0 || cacheId
>= SysCacheSize
||
1030 !PointerIsValid(SysCache
[cacheId
]))
1031 elog(ERROR
, "invalid cache id: %d", cacheId
);
1032 if (!PointerIsValid(SysCache
[cacheId
]->cc_tupdesc
))
1034 InitCatCachePhase2(SysCache
[cacheId
], false);
1035 Assert(PointerIsValid(SysCache
[cacheId
]->cc_tupdesc
));
1038 return heap_getattr(tup
, attributeNumber
,
1039 SysCache
[cacheId
]->cc_tupdesc
,
1044 * List-search interface
1047 SearchSysCacheList(int cacheId
, int nkeys
,
1048 Datum key1
, Datum key2
, Datum key3
, Datum key4
)
1050 if (cacheId
< 0 || cacheId
>= SysCacheSize
||
1051 !PointerIsValid(SysCache
[cacheId
]))
1052 elog(ERROR
, "invalid cache id: %d", cacheId
);
1054 return SearchCatCacheList(SysCache
[cacheId
], nkeys
,
1055 key1
, key2
, key3
, key4
);