1 /*-------------------------------------------------------------------------
4 * System cache management routines
6 * Portions Copyright (c) 1996-2017, 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 IDs
19 *-------------------------------------------------------------------------
23 #include "access/htup_details.h"
24 #include "access/sysattr.h"
25 #include "catalog/indexing.h"
26 #include "catalog/pg_aggregate.h"
27 #include "catalog/pg_am.h"
28 #include "catalog/pg_amop.h"
29 #include "catalog/pg_amproc.h"
30 #include "catalog/pg_auth_members.h"
31 #include "catalog/pg_authid.h"
32 #include "catalog/pg_cast.h"
33 #include "catalog/pg_collation.h"
34 #include "catalog/pg_constraint.h"
35 #include "catalog/pg_conversion.h"
36 #include "catalog/pg_database.h"
37 #include "catalog/pg_db_role_setting.h"
38 #include "catalog/pg_default_acl.h"
39 #include "catalog/pg_depend.h"
40 #include "catalog/pg_description.h"
41 #include "catalog/pg_enum.h"
42 #include "catalog/pg_event_trigger.h"
43 #include "catalog/pg_foreign_data_wrapper.h"
44 #include "catalog/pg_foreign_server.h"
45 #include "catalog/pg_foreign_table.h"
46 #include "catalog/pg_language.h"
47 #include "catalog/pg_namespace.h"
48 #include "catalog/pg_opclass.h"
49 #include "catalog/pg_operator.h"
50 #include "catalog/pg_opfamily.h"
51 #include "catalog/pg_partitioned_table.h"
52 #include "catalog/pg_proc.h"
53 #include "catalog/pg_publication.h"
54 #include "catalog/pg_publication_rel.h"
55 #include "catalog/pg_range.h"
56 #include "catalog/pg_rewrite.h"
57 #include "catalog/pg_seclabel.h"
58 #include "catalog/pg_sequence.h"
59 #include "catalog/pg_shdepend.h"
60 #include "catalog/pg_shdescription.h"
61 #include "catalog/pg_shseclabel.h"
62 #include "catalog/pg_replication_origin.h"
63 #include "catalog/pg_statistic.h"
64 #include "catalog/pg_statistic_ext.h"
65 #include "catalog/pg_subscription.h"
66 #include "catalog/pg_subscription_rel.h"
67 #include "catalog/pg_tablespace.h"
68 #include "catalog/pg_transform.h"
69 #include "catalog/pg_ts_config.h"
70 #include "catalog/pg_ts_config_map.h"
71 #include "catalog/pg_ts_dict.h"
72 #include "catalog/pg_ts_parser.h"
73 #include "catalog/pg_ts_template.h"
74 #include "catalog/pg_type.h"
75 #include "catalog/pg_user_mapping.h"
76 #include "utils/rel.h"
77 #include "utils/catcache.h"
78 #include "utils/syscache.h"
81 /*---------------------------------------------------------------------------
85 Add your new cache to the list in include/utils/syscache.h.
86 Keep the list sorted alphabetically.
88 Add your entry to the cacheinfo[] array below. All cache lists are
89 alphabetical, so add it in the proper place. Specify the relation OID,
90 index OID, number of keys, key attribute numbers, and initial number of
93 The number of hash buckets must be a power of 2. It's reasonable to
94 set this to the number of entries that might be in the particular cache
95 in a medium-size database.
97 There must be a unique index underlying each syscache (ie, an index
98 whose key is the same as that of the cache). If there is not one
99 already, add definitions for it to include/catalog/indexing.h: you need
100 to add a DECLARE_UNIQUE_INDEX macro and a #define for the index OID.
101 (Adding an index requires a catversion.h update, while simply
102 adding/deleting caches only requires a recompile.)
104 Finally, any place your relation gets heap_insert() or
105 heap_update() calls, use CatalogTupleInsert() or CatalogTupleUpdate()
106 instead, which also update indexes. The heap_* calls do not do that.
108 *---------------------------------------------------------------------------
112 * struct cachedesc: information defining a single syscache
116 Oid reloid; /* OID of the relation being cached */
117 Oid indoid; /* OID of index relation for this cache */
118 int nkeys; /* # of keys needed for cache lookup */
119 int key[4]; /* attribute numbers of key attrs */
120 int nbuckets; /* number of hash buckets for this cache */
123 static const struct cachedesc cacheinfo[] = {
124 {AggregateRelationId, /* AGGFNOID */
125 AggregateFnoidIndexId,
128 Anum_pg_aggregate_aggfnoid,
135 {AccessMethodRelationId, /* AMNAME */
146 {AccessMethodRelationId, /* AMOID */
150 ObjectIdAttributeNumber,
157 {AccessMethodOperatorRelationId, /* AMOPOPID */
158 AccessMethodOperatorIndexId,
161 Anum_pg_amop_amopopr,
162 Anum_pg_amop_amoppurpose,
163 Anum_pg_amop_amopfamily,
168 {AccessMethodOperatorRelationId, /* AMOPSTRATEGY */
169 AccessMethodStrategyIndexId,
172 Anum_pg_amop_amopfamily,
173 Anum_pg_amop_amoplefttype,
174 Anum_pg_amop_amoprighttype,
175 Anum_pg_amop_amopstrategy
179 {AccessMethodProcedureRelationId, /* AMPROCNUM */
180 AccessMethodProcedureIndexId,
183 Anum_pg_amproc_amprocfamily,
184 Anum_pg_amproc_amproclefttype,
185 Anum_pg_amproc_amprocrighttype,
186 Anum_pg_amproc_amprocnum
190 {AttributeRelationId, /* ATTNAME */
191 AttributeRelidNameIndexId,
194 Anum_pg_attribute_attrelid,
195 Anum_pg_attribute_attname,
201 {AttributeRelationId, /* ATTNUM */
202 AttributeRelidNumIndexId,
205 Anum_pg_attribute_attrelid,
206 Anum_pg_attribute_attnum,
212 {AuthMemRelationId, /* AUTHMEMMEMROLE */
213 AuthMemMemRoleIndexId,
216 Anum_pg_auth_members_member,
217 Anum_pg_auth_members_roleid,
223 {AuthMemRelationId, /* AUTHMEMROLEMEM */
224 AuthMemRoleMemIndexId,
227 Anum_pg_auth_members_roleid,
228 Anum_pg_auth_members_member,
234 {AuthIdRelationId, /* AUTHNAME */
235 AuthIdRolnameIndexId,
238 Anum_pg_authid_rolname,
245 {AuthIdRelationId, /* AUTHOID */
249 ObjectIdAttributeNumber,
257 CastRelationId, /* CASTSOURCETARGET */
258 CastSourceTargetIndexId,
261 Anum_pg_cast_castsource,
262 Anum_pg_cast_casttarget,
268 {OperatorClassRelationId, /* CLAAMNAMENSP */
269 OpclassAmNameNspIndexId,
272 Anum_pg_opclass_opcmethod,
273 Anum_pg_opclass_opcname,
274 Anum_pg_opclass_opcnamespace,
279 {OperatorClassRelationId, /* CLAOID */
283 ObjectIdAttributeNumber,
290 {CollationRelationId, /* COLLNAMEENCNSP */
291 CollationNameEncNspIndexId,
294 Anum_pg_collation_collname,
295 Anum_pg_collation_collencoding,
296 Anum_pg_collation_collnamespace,
301 {CollationRelationId, /* COLLOID */
305 ObjectIdAttributeNumber,
312 {ConversionRelationId, /* CONDEFAULT */
313 ConversionDefaultIndexId,
316 Anum_pg_conversion_connamespace,
317 Anum_pg_conversion_conforencoding,
318 Anum_pg_conversion_contoencoding,
319 ObjectIdAttributeNumber,
323 {ConversionRelationId, /* CONNAMENSP */
324 ConversionNameNspIndexId,
327 Anum_pg_conversion_conname,
328 Anum_pg_conversion_connamespace,
334 {ConstraintRelationId, /* CONSTROID */
335 ConstraintOidIndexId,
338 ObjectIdAttributeNumber,
345 {ConversionRelationId, /* CONVOID */
346 ConversionOidIndexId,
349 ObjectIdAttributeNumber,
356 {DatabaseRelationId, /* DATABASEOID */
360 ObjectIdAttributeNumber,
367 {DefaultAclRelationId, /* DEFACLROLENSPOBJ */
368 DefaultAclRoleNspObjIndexId,
371 Anum_pg_default_acl_defaclrole,
372 Anum_pg_default_acl_defaclnamespace,
373 Anum_pg_default_acl_defaclobjtype,
378 {EnumRelationId, /* ENUMOID */
382 ObjectIdAttributeNumber,
389 {EnumRelationId, /* ENUMTYPOIDNAME */
390 EnumTypIdLabelIndexId,
393 Anum_pg_enum_enumtypid,
394 Anum_pg_enum_enumlabel,
400 {EventTriggerRelationId, /* EVENTTRIGGERNAME */
401 EventTriggerNameIndexId,
404 Anum_pg_event_trigger_evtname,
411 {EventTriggerRelationId, /* EVENTTRIGGEROID */
412 EventTriggerOidIndexId,
415 ObjectIdAttributeNumber,
422 {ForeignDataWrapperRelationId, /* FOREIGNDATAWRAPPERNAME */
423 ForeignDataWrapperNameIndexId,
426 Anum_pg_foreign_data_wrapper_fdwname,
433 {ForeignDataWrapperRelationId, /* FOREIGNDATAWRAPPEROID */
434 ForeignDataWrapperOidIndexId,
437 ObjectIdAttributeNumber,
444 {ForeignServerRelationId, /* FOREIGNSERVERNAME */
445 ForeignServerNameIndexId,
448 Anum_pg_foreign_server_srvname,
455 {ForeignServerRelationId, /* FOREIGNSERVEROID */
456 ForeignServerOidIndexId,
459 ObjectIdAttributeNumber,
466 {ForeignTableRelationId, /* FOREIGNTABLEREL */
467 ForeignTableRelidIndexId,
470 Anum_pg_foreign_table_ftrelid,
477 {IndexRelationId, /* INDEXRELID */
481 Anum_pg_index_indexrelid,
488 {LanguageRelationId, /* LANGNAME */
492 Anum_pg_language_lanname,
499 {LanguageRelationId, /* LANGOID */
503 ObjectIdAttributeNumber,
510 {NamespaceRelationId, /* NAMESPACENAME */
511 NamespaceNameIndexId,
514 Anum_pg_namespace_nspname,
521 {NamespaceRelationId, /* NAMESPACEOID */
525 ObjectIdAttributeNumber,
532 {OperatorRelationId, /* OPERNAMENSP */
533 OperatorNameNspIndexId,
536 Anum_pg_operator_oprname,
537 Anum_pg_operator_oprleft,
538 Anum_pg_operator_oprright,
539 Anum_pg_operator_oprnamespace
543 {OperatorRelationId, /* OPEROID */
547 ObjectIdAttributeNumber,
554 {OperatorFamilyRelationId, /* OPFAMILYAMNAMENSP */
555 OpfamilyAmNameNspIndexId,
558 Anum_pg_opfamily_opfmethod,
559 Anum_pg_opfamily_opfname,
560 Anum_pg_opfamily_opfnamespace,
565 {OperatorFamilyRelationId, /* OPFAMILYOID */
569 ObjectIdAttributeNumber,
576 {PartitionedRelationId, /* PARTRELID */
577 PartitionedRelidIndexId,
580 Anum_pg_partitioned_table_partrelid,
587 {ProcedureRelationId, /* PROCNAMEARGSNSP */
588 ProcedureNameArgsNspIndexId,
591 Anum_pg_proc_proname,
592 Anum_pg_proc_proargtypes,
593 Anum_pg_proc_pronamespace,
598 {ProcedureRelationId, /* PROCOID */
602 ObjectIdAttributeNumber,
609 {RangeRelationId, /* RANGETYPE */
613 Anum_pg_range_rngtypid,
620 {RelationRelationId, /* RELNAMENSP */
624 Anum_pg_class_relname,
625 Anum_pg_class_relnamespace,
631 {RelationRelationId, /* RELOID */
635 ObjectIdAttributeNumber,
642 {ReplicationOriginRelationId, /* REPLORIGIDENT */
643 ReplicationOriginIdentIndex,
646 Anum_pg_replication_origin_roident,
653 {ReplicationOriginRelationId, /* REPLORIGNAME */
654 ReplicationOriginNameIndex,
657 Anum_pg_replication_origin_roname,
664 {PublicationRelationId, /* PUBLICATIONOID */
665 PublicationObjectIndexId,
668 ObjectIdAttributeNumber,
675 {PublicationRelationId, /* PUBLICATIONNAME */
676 PublicationNameIndexId,
679 Anum_pg_publication_pubname,
686 {PublicationRelRelationId, /* PUBLICATIONREL */
687 PublicationRelObjectIndexId,
690 ObjectIdAttributeNumber,
697 {PublicationRelRelationId, /* PUBLICATIONRELMAP */
698 PublicationRelPrrelidPrpubidIndexId,
701 Anum_pg_publication_rel_prrelid,
702 Anum_pg_publication_rel_prpubid,
708 {RewriteRelationId, /* RULERELNAME */
709 RewriteRelRulenameIndexId,
712 Anum_pg_rewrite_ev_class,
713 Anum_pg_rewrite_rulename,
719 {SequenceRelationId, /* SEQRELID */
720 SequenceRelidIndexId,
723 Anum_pg_sequence_seqrelid,
730 {StatisticExtRelationId, /* STATEXTNAMENSP */
731 StatisticExtNameIndexId,
734 Anum_pg_statistic_ext_staname,
735 Anum_pg_statistic_ext_stanamespace,
741 {StatisticExtRelationId, /* STATEXTOID */
742 StatisticExtOidIndexId,
745 ObjectIdAttributeNumber,
752 {StatisticRelationId, /* STATRELATTINH */
753 StatisticRelidAttnumInhIndexId,
756 Anum_pg_statistic_starelid,
757 Anum_pg_statistic_staattnum,
758 Anum_pg_statistic_stainherit,
763 {SubscriptionRelationId, /* SUBSCRIPTIONOID */
764 SubscriptionObjectIndexId,
767 ObjectIdAttributeNumber,
774 {SubscriptionRelationId, /* SUBSCRIPTIONNAME */
775 SubscriptionNameIndexId,
778 Anum_pg_subscription_subdbid,
779 Anum_pg_subscription_subname,
785 {SubscriptionRelRelationId, /* SUBSCRIPTIONRELMAP */
786 SubscriptionRelSrrelidSrsubidIndexId,
789 Anum_pg_subscription_rel_srrelid,
790 Anum_pg_subscription_rel_srsubid,
796 {TableSpaceRelationId, /* TABLESPACEOID */
797 TablespaceOidIndexId,
800 ObjectIdAttributeNumber,
807 {TransformRelationId, /* TRFOID */
811 ObjectIdAttributeNumber,
818 {TransformRelationId, /* TRFTYPELANG */
819 TransformTypeLangIndexId,
822 Anum_pg_transform_trftype,
823 Anum_pg_transform_trflang,
829 {TSConfigMapRelationId, /* TSCONFIGMAP */
833 Anum_pg_ts_config_map_mapcfg,
834 Anum_pg_ts_config_map_maptokentype,
835 Anum_pg_ts_config_map_mapseqno,
840 {TSConfigRelationId, /* TSCONFIGNAMENSP */
841 TSConfigNameNspIndexId,
844 Anum_pg_ts_config_cfgname,
845 Anum_pg_ts_config_cfgnamespace,
851 {TSConfigRelationId, /* TSCONFIGOID */
855 ObjectIdAttributeNumber,
862 {TSDictionaryRelationId, /* TSDICTNAMENSP */
863 TSDictionaryNameNspIndexId,
866 Anum_pg_ts_dict_dictname,
867 Anum_pg_ts_dict_dictnamespace,
873 {TSDictionaryRelationId, /* TSDICTOID */
874 TSDictionaryOidIndexId,
877 ObjectIdAttributeNumber,
884 {TSParserRelationId, /* TSPARSERNAMENSP */
885 TSParserNameNspIndexId,
888 Anum_pg_ts_parser_prsname,
889 Anum_pg_ts_parser_prsnamespace,
895 {TSParserRelationId, /* TSPARSEROID */
899 ObjectIdAttributeNumber,
906 {TSTemplateRelationId, /* TSTEMPLATENAMENSP */
907 TSTemplateNameNspIndexId,
910 Anum_pg_ts_template_tmplname,
911 Anum_pg_ts_template_tmplnamespace,
917 {TSTemplateRelationId, /* TSTEMPLATEOID */
918 TSTemplateOidIndexId,
921 ObjectIdAttributeNumber,
928 {TypeRelationId, /* TYPENAMENSP */
932 Anum_pg_type_typname,
933 Anum_pg_type_typnamespace,
939 {TypeRelationId, /* TYPEOID */
943 ObjectIdAttributeNumber,
950 {UserMappingRelationId, /* USERMAPPINGOID */
951 UserMappingOidIndexId,
954 ObjectIdAttributeNumber,
961 {UserMappingRelationId, /* USERMAPPINGUSERSERVER */
962 UserMappingUserServerIndexId,
965 Anum_pg_user_mapping_umuser,
966 Anum_pg_user_mapping_umserver,
974 #define SysCacheSize ((int) lengthof(cacheinfo))
976 static CatCache *SysCache[SysCacheSize];
978 static bool CacheInitialized = false;
980 /* Sorted array of OIDs of tables that have caches on them */
981 static Oid SysCacheRelationOid[SysCacheSize];
982 static int SysCacheRelationOidSize;
984 /* Sorted array of OIDs of tables and indexes used by caches */
985 static Oid SysCacheSupportingRelOid[SysCacheSize * 2];
986 static int SysCacheSupportingRelOidSize;
988 static int oid_compare(const void *a, const void *b);
992 * InitCatalogCache - initialize the caches
994 * Note that no database access is done here; we only allocate memory
995 * and initialize the cache structure. Interrogation of the database
996 * to complete initialization of a cache happens upon first use
1000 InitCatalogCache(void)
1006 Assert(!CacheInitialized);
1008 SysCacheRelationOidSize = SysCacheSupportingRelOidSize = 0;
1010 for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
1012 SysCache[cacheId] = InitCatCache(cacheId,
1013 cacheinfo[cacheId].reloid,
1014 cacheinfo[cacheId].indoid,
1015 cacheinfo[cacheId].nkeys,
1016 cacheinfo[cacheId].key,
1017 cacheinfo[cacheId].nbuckets);
1018 if (!PointerIsValid(SysCache[cacheId]))
1019 elog(ERROR, "could not initialize cache %u (%d)",
1020 cacheinfo[cacheId].reloid, cacheId);
1021 /* Accumulate data for OID lists, too */
1022 SysCacheRelationOid[SysCacheRelationOidSize++] =
1023 cacheinfo[cacheId].reloid;
1024 SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
1025 cacheinfo[cacheId].reloid;
1026 SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
1027 cacheinfo[cacheId].indoid;
1028 /* see comments for RelationInvalidatesSnapshotsOnly */
1029 Assert(!RelationInvalidatesSnapshotsOnly(cacheinfo[cacheId].reloid));
1032 Assert(SysCacheRelationOidSize <= lengthof(SysCacheRelationOid));
1033 Assert(SysCacheSupportingRelOidSize <= lengthof(SysCacheSupportingRelOid));
1035 /* Sort and de-dup OID arrays, so we can use binary search. */
1036 pg_qsort(SysCacheRelationOid, SysCacheRelationOidSize,
1037 sizeof(Oid), oid_compare);
1038 for (i = 1, j = 0; i < SysCacheRelationOidSize; i++)
1040 if (SysCacheRelationOid[i] != SysCacheRelationOid[j])
1041 SysCacheRelationOid[++j] = SysCacheRelationOid[i];
1043 SysCacheRelationOidSize = j + 1;
1045 pg_qsort(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
1046 sizeof(Oid), oid_compare);
1047 for (i = 1, j = 0; i < SysCacheSupportingRelOidSize; i++)
1049 if (SysCacheSupportingRelOid[i] != SysCacheSupportingRelOid[j])
1050 SysCacheSupportingRelOid[++j] = SysCacheSupportingRelOid[i];
1052 SysCacheSupportingRelOidSize = j + 1;
1054 CacheInitialized = true;
1058 * InitCatalogCachePhase2 - finish initializing the caches
1060 * Finish initializing all the caches, including necessary database
1063 * This is *not* essential; normally we allow syscaches to be initialized
1064 * on first use. However, it is useful as a mechanism to preload the
1065 * relcache with entries for the most-commonly-used system catalogs.
1066 * Therefore, we invoke this routine when we need to write a new relcache
1070 InitCatalogCachePhase2(void)
1074 Assert(CacheInitialized);
1076 for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
1077 InitCatCachePhase2(SysCache[cacheId], true);
1084 * A layer on top of SearchCatCache that does the initialization and
1085 * key-setting for you.
1087 * Returns the cache copy of the tuple if one is found, NULL if not.
1088 * The tuple is the 'cache' copy and must NOT be modified!
1090 * When the caller is done using the tuple, call ReleaseSysCache()
1091 * to release the reference count grabbed by SearchSysCache(). If this
1092 * is not done, the tuple will remain locked in cache until end of
1093 * transaction, which is tolerable but not desirable.
1095 * CAUTION: The tuple that is returned must NOT be freed by the caller!
1098 SearchSysCache(int cacheId,
1104 if (cacheId < 0 || cacheId >= SysCacheSize ||
1105 !PointerIsValid(SysCache[cacheId]))
1106 elog(ERROR, "invalid cache ID: %d", cacheId);
1108 return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
1113 * Release previously grabbed reference count on a tuple
1116 ReleaseSysCache(HeapTuple tuple)
1118 ReleaseCatCache(tuple);
1122 * SearchSysCacheCopy
1124 * A convenience routine that does SearchSysCache and (if successful)
1125 * returns a modifiable copy of the syscache entry. The original
1126 * syscache entry is released before returning. The caller should
1127 * heap_freetuple() the result when done with it.
1130 SearchSysCacheCopy(int cacheId,
1139 tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1140 if (!HeapTupleIsValid(tuple))
1142 newtuple = heap_copytuple(tuple);
1143 ReleaseSysCache(tuple);
1148 * SearchSysCacheExists
1150 * A convenience routine that just probes to see if a tuple can be found.
1151 * No lock is retained on the syscache entry.
1154 SearchSysCacheExists(int cacheId,
1162 tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1163 if (!HeapTupleIsValid(tuple))
1165 ReleaseSysCache(tuple);
1172 * A convenience routine that does SearchSysCache and returns the OID
1173 * of the found tuple, or InvalidOid if no tuple could be found.
1174 * No lock is retained on the syscache entry.
1177 GetSysCacheOid(int cacheId,
1186 tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1187 if (!HeapTupleIsValid(tuple))
1189 result = HeapTupleGetOid(tuple);
1190 ReleaseSysCache(tuple);
1196 * SearchSysCacheAttName
1198 * This routine is equivalent to SearchSysCache on the ATTNAME cache,
1199 * except that it will return NULL if the found attribute is marked
1200 * attisdropped. This is convenient for callers that want to act as
1201 * though dropped attributes don't exist.
1204 SearchSysCacheAttName(Oid relid, const char *attname)
1208 tuple = SearchSysCache2(ATTNAME,
1209 ObjectIdGetDatum(relid),
1210 CStringGetDatum(attname));
1211 if (!HeapTupleIsValid(tuple))
1213 if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
1215 ReleaseSysCache(tuple);
1222 * SearchSysCacheCopyAttName
1224 * As above, an attisdropped-aware version of SearchSysCacheCopy.
1227 SearchSysCacheCopyAttName(Oid relid, const char *attname)
1232 tuple = SearchSysCacheAttName(relid, attname);
1233 if (!HeapTupleIsValid(tuple))
1235 newtuple = heap_copytuple(tuple);
1236 ReleaseSysCache(tuple);
1241 * SearchSysCacheExistsAttName
1243 * As above, an attisdropped-aware version of SearchSysCacheExists.
1246 SearchSysCacheExistsAttName(Oid relid, const char *attname)
1250 tuple = SearchSysCacheAttName(relid, attname);
1251 if (!HeapTupleIsValid(tuple))
1253 ReleaseSysCache(tuple);
1261 * Given a tuple previously fetched by SearchSysCache(),
1262 * extract a specific attribute.
1264 * This is equivalent to using heap_getattr() on a tuple fetched
1265 * from a non-cached relation. Usually, this is only used for attributes
1266 * that could be NULL or variable length; the fixed-size attributes in
1267 * a system table are accessed just by mapping the tuple onto the C struct
1268 * declarations from include/catalog/.
1270 * As with heap_getattr(), if the attribute is of a pass-by-reference type
1271 * then a pointer into the tuple data area is returned --- the caller must
1272 * not modify or pfree the datum!
1274 * Note: it is legal to use SysCacheGetAttr() with a cacheId referencing
1275 * a different cache for the same catalog the tuple was fetched from.
1278 SysCacheGetAttr(int cacheId, HeapTuple tup,
1279 AttrNumber attributeNumber,
1283 * We just need to get the TupleDesc out of the cache entry, and then we
1284 * can apply heap_getattr(). Normally the cache control data is already
1285 * valid (because the caller recently fetched the tuple via this same
1286 * cache), but there are cases where we have to initialize the cache here.
1288 if (cacheId < 0 || cacheId >= SysCacheSize ||
1289 !PointerIsValid(SysCache[cacheId]))
1290 elog(ERROR, "invalid cache ID: %d", cacheId);
1291 if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
1293 InitCatCachePhase2(SysCache[cacheId], false);
1294 Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
1297 return heap_getattr(tup, attributeNumber,
1298 SysCache[cacheId]->cc_tupdesc,
1303 * GetSysCacheHashValue
1305 * Get the hash value that would be used for a tuple in the specified cache
1306 * with the given search keys.
1308 * The reason for exposing this as part of the API is that the hash value is
1309 * exposed in cache invalidation operations, so there are places outside the
1310 * catcache code that need to be able to compute the hash values.
1313 GetSysCacheHashValue(int cacheId,
1319 if (cacheId < 0 || cacheId >= SysCacheSize ||
1320 !PointerIsValid(SysCache[cacheId]))
1321 elog(ERROR, "invalid cache ID: %d", cacheId);
1323 return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
1327 * List-search interface
1330 SearchSysCacheList(int cacheId, int nkeys,
1331 Datum key1, Datum key2, Datum key3, Datum key4)
1333 if (cacheId < 0 || cacheId >= SysCacheSize ||
1334 !PointerIsValid(SysCache[cacheId]))
1335 elog(ERROR, "invalid cache ID: %d", cacheId);
1337 return SearchCatCacheList(SysCache[cacheId], nkeys,
1338 key1, key2, key3, key4);
1342 * Certain relations that do not have system caches send snapshot invalidation
1343 * messages in lieu of catcache messages. This is for the benefit of
1344 * GetCatalogSnapshot(), which can then reuse its existing MVCC snapshot
1345 * for scanning one of those catalogs, rather than taking a new one, if no
1346 * invalidation has been received.
1348 * Relations that have syscaches need not (and must not) be listed here. The
1349 * catcache invalidation messages will also flush the snapshot. If you add a
1350 * syscache for one of these relations, remove it from this list.
1353 RelationInvalidatesSnapshotsOnly(Oid relid)
1357 case DbRoleSettingRelationId:
1358 case DependRelationId:
1359 case SharedDependRelationId:
1360 case DescriptionRelationId:
1361 case SharedDescriptionRelationId:
1362 case SecLabelRelationId:
1363 case SharedSecLabelRelationId:
1373 * Test whether a relation has a system cache.
1376 RelationHasSysCache(Oid relid)
1379 high = SysCacheRelationOidSize - 1;
1383 int middle = low + (high - low) / 2;
1385 if (SysCacheRelationOid[middle] == relid)
1387 if (SysCacheRelationOid[middle] < relid)
1397 * Test whether a relation supports a system cache, ie it is either a
1398 * cached table or the index used for a cache.
1401 RelationSupportsSysCache(Oid relid)
1404 high = SysCacheSupportingRelOidSize - 1;
1408 int middle = low + (high - low) / 2;
1410 if (SysCacheSupportingRelOid[middle] == relid)
1412 if (SysCacheSupportingRelOid[middle] < relid)
1423 * OID comparator for pg_qsort
1426 oid_compare(const void *a, const void *b)
1428 Oid oa = *((const Oid *) a);
1429 Oid ob = *((const Oid *) b);
1433 return (oa > ob) ? 1 : -1;