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_stxname,
735 Anum_pg_statistic_ext_stxnamespace,
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 static CatCache *SysCache[SysCacheSize];
976 static bool CacheInitialized = false;
978 /* Sorted array of OIDs of tables that have caches on them */
979 static Oid SysCacheRelationOid[SysCacheSize];
980 static int SysCacheRelationOidSize;
982 /* Sorted array of OIDs of tables and indexes used by caches */
983 static Oid SysCacheSupportingRelOid[SysCacheSize * 2];
984 static int SysCacheSupportingRelOidSize;
986 static int oid_compare(const void *a, const void *b);
990 * InitCatalogCache - initialize the caches
992 * Note that no database access is done here; we only allocate memory
993 * and initialize the cache structure. Interrogation of the database
994 * to complete initialization of a cache happens upon first use
998 InitCatalogCache(void)
1004 StaticAssertStmt(SysCacheSize == (int) lengthof(cacheinfo),
1005 "SysCacheSize does not match syscache.c's array");
1007 Assert(!CacheInitialized);
1009 SysCacheRelationOidSize = SysCacheSupportingRelOidSize = 0;
1011 for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
1013 SysCache[cacheId] = InitCatCache(cacheId,
1014 cacheinfo[cacheId].reloid,
1015 cacheinfo[cacheId].indoid,
1016 cacheinfo[cacheId].nkeys,
1017 cacheinfo[cacheId].key,
1018 cacheinfo[cacheId].nbuckets);
1019 if (!PointerIsValid(SysCache[cacheId]))
1020 elog(ERROR, "could not initialize cache %u (%d)",
1021 cacheinfo[cacheId].reloid, cacheId);
1022 /* Accumulate data for OID lists, too */
1023 SysCacheRelationOid[SysCacheRelationOidSize++] =
1024 cacheinfo[cacheId].reloid;
1025 SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
1026 cacheinfo[cacheId].reloid;
1027 SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
1028 cacheinfo[cacheId].indoid;
1029 /* see comments for RelationInvalidatesSnapshotsOnly */
1030 Assert(!RelationInvalidatesSnapshotsOnly(cacheinfo[cacheId].reloid));
1033 Assert(SysCacheRelationOidSize <= lengthof(SysCacheRelationOid));
1034 Assert(SysCacheSupportingRelOidSize <= lengthof(SysCacheSupportingRelOid));
1036 /* Sort and de-dup OID arrays, so we can use binary search. */
1037 pg_qsort(SysCacheRelationOid, SysCacheRelationOidSize,
1038 sizeof(Oid), oid_compare);
1039 for (i = 1, j = 0; i < SysCacheRelationOidSize; i++)
1041 if (SysCacheRelationOid[i] != SysCacheRelationOid[j])
1042 SysCacheRelationOid[++j] = SysCacheRelationOid[i];
1044 SysCacheRelationOidSize = j + 1;
1046 pg_qsort(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
1047 sizeof(Oid), oid_compare);
1048 for (i = 1, j = 0; i < SysCacheSupportingRelOidSize; i++)
1050 if (SysCacheSupportingRelOid[i] != SysCacheSupportingRelOid[j])
1051 SysCacheSupportingRelOid[++j] = SysCacheSupportingRelOid[i];
1053 SysCacheSupportingRelOidSize = j + 1;
1055 CacheInitialized = true;
1059 * InitCatalogCachePhase2 - finish initializing the caches
1061 * Finish initializing all the caches, including necessary database
1064 * This is *not* essential; normally we allow syscaches to be initialized
1065 * on first use. However, it is useful as a mechanism to preload the
1066 * relcache with entries for the most-commonly-used system catalogs.
1067 * Therefore, we invoke this routine when we need to write a new relcache
1071 InitCatalogCachePhase2(void)
1075 Assert(CacheInitialized);
1077 for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
1078 InitCatCachePhase2(SysCache[cacheId], true);
1085 * A layer on top of SearchCatCache that does the initialization and
1086 * key-setting for you.
1088 * Returns the cache copy of the tuple if one is found, NULL if not.
1089 * The tuple is the 'cache' copy and must NOT be modified!
1091 * When the caller is done using the tuple, call ReleaseSysCache()
1092 * to release the reference count grabbed by SearchSysCache(). If this
1093 * is not done, the tuple will remain locked in cache until end of
1094 * transaction, which is tolerable but not desirable.
1096 * CAUTION: The tuple that is returned must NOT be freed by the caller!
1099 SearchSysCache(int cacheId,
1105 if (cacheId < 0 || cacheId >= SysCacheSize ||
1106 !PointerIsValid(SysCache[cacheId]))
1107 elog(ERROR, "invalid cache ID: %d", cacheId);
1109 return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
1114 * Release previously grabbed reference count on a tuple
1117 ReleaseSysCache(HeapTuple tuple)
1119 ReleaseCatCache(tuple);
1123 * SearchSysCacheCopy
1125 * A convenience routine that does SearchSysCache and (if successful)
1126 * returns a modifiable copy of the syscache entry. The original
1127 * syscache entry is released before returning. The caller should
1128 * heap_freetuple() the result when done with it.
1131 SearchSysCacheCopy(int cacheId,
1140 tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1141 if (!HeapTupleIsValid(tuple))
1143 newtuple = heap_copytuple(tuple);
1144 ReleaseSysCache(tuple);
1149 * SearchSysCacheExists
1151 * A convenience routine that just probes to see if a tuple can be found.
1152 * No lock is retained on the syscache entry.
1155 SearchSysCacheExists(int cacheId,
1163 tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1164 if (!HeapTupleIsValid(tuple))
1166 ReleaseSysCache(tuple);
1173 * A convenience routine that does SearchSysCache and returns the OID
1174 * of the found tuple, or InvalidOid if no tuple could be found.
1175 * No lock is retained on the syscache entry.
1178 GetSysCacheOid(int cacheId,
1187 tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1188 if (!HeapTupleIsValid(tuple))
1190 result = HeapTupleGetOid(tuple);
1191 ReleaseSysCache(tuple);
1197 * SearchSysCacheAttName
1199 * This routine is equivalent to SearchSysCache on the ATTNAME cache,
1200 * except that it will return NULL if the found attribute is marked
1201 * attisdropped. This is convenient for callers that want to act as
1202 * though dropped attributes don't exist.
1205 SearchSysCacheAttName(Oid relid, const char *attname)
1209 tuple = SearchSysCache2(ATTNAME,
1210 ObjectIdGetDatum(relid),
1211 CStringGetDatum(attname));
1212 if (!HeapTupleIsValid(tuple))
1214 if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
1216 ReleaseSysCache(tuple);
1223 * SearchSysCacheCopyAttName
1225 * As above, an attisdropped-aware version of SearchSysCacheCopy.
1228 SearchSysCacheCopyAttName(Oid relid, const char *attname)
1233 tuple = SearchSysCacheAttName(relid, attname);
1234 if (!HeapTupleIsValid(tuple))
1236 newtuple = heap_copytuple(tuple);
1237 ReleaseSysCache(tuple);
1242 * SearchSysCacheExistsAttName
1244 * As above, an attisdropped-aware version of SearchSysCacheExists.
1247 SearchSysCacheExistsAttName(Oid relid, const char *attname)
1251 tuple = SearchSysCacheAttName(relid, attname);
1252 if (!HeapTupleIsValid(tuple))
1254 ReleaseSysCache(tuple);
1262 * Given a tuple previously fetched by SearchSysCache(),
1263 * extract a specific attribute.
1265 * This is equivalent to using heap_getattr() on a tuple fetched
1266 * from a non-cached relation. Usually, this is only used for attributes
1267 * that could be NULL or variable length; the fixed-size attributes in
1268 * a system table are accessed just by mapping the tuple onto the C struct
1269 * declarations from include/catalog/.
1271 * As with heap_getattr(), if the attribute is of a pass-by-reference type
1272 * then a pointer into the tuple data area is returned --- the caller must
1273 * not modify or pfree the datum!
1275 * Note: it is legal to use SysCacheGetAttr() with a cacheId referencing
1276 * a different cache for the same catalog the tuple was fetched from.
1279 SysCacheGetAttr(int cacheId, HeapTuple tup,
1280 AttrNumber attributeNumber,
1284 * We just need to get the TupleDesc out of the cache entry, and then we
1285 * can apply heap_getattr(). Normally the cache control data is already
1286 * valid (because the caller recently fetched the tuple via this same
1287 * cache), but there are cases where we have to initialize the cache here.
1289 if (cacheId < 0 || cacheId >= SysCacheSize ||
1290 !PointerIsValid(SysCache[cacheId]))
1291 elog(ERROR, "invalid cache ID: %d", cacheId);
1292 if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
1294 InitCatCachePhase2(SysCache[cacheId], false);
1295 Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
1298 return heap_getattr(tup, attributeNumber,
1299 SysCache[cacheId]->cc_tupdesc,
1304 * GetSysCacheHashValue
1306 * Get the hash value that would be used for a tuple in the specified cache
1307 * with the given search keys.
1309 * The reason for exposing this as part of the API is that the hash value is
1310 * exposed in cache invalidation operations, so there are places outside the
1311 * catcache code that need to be able to compute the hash values.
1314 GetSysCacheHashValue(int cacheId,
1320 if (cacheId < 0 || cacheId >= SysCacheSize ||
1321 !PointerIsValid(SysCache[cacheId]))
1322 elog(ERROR, "invalid cache ID: %d", cacheId);
1324 return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
1328 * List-search interface
1331 SearchSysCacheList(int cacheId, int nkeys,
1332 Datum key1, Datum key2, Datum key3, Datum key4)
1334 if (cacheId < 0 || cacheId >= SysCacheSize ||
1335 !PointerIsValid(SysCache[cacheId]))
1336 elog(ERROR, "invalid cache ID: %d", cacheId);
1338 return SearchCatCacheList(SysCache[cacheId], nkeys,
1339 key1, key2, key3, key4);
1343 * SysCacheInvalidate
1345 * Invalidate entries in the specified cache, given a hash value.
1346 * See CatCacheInvalidate() for more info.
1348 * This routine is only quasi-public: it should only be used by inval.c.
1351 SysCacheInvalidate(int cacheId, uint32 hashValue)
1353 if (cacheId < 0 || cacheId >= SysCacheSize)
1354 elog(ERROR, "invalid cache ID: %d", cacheId);
1356 /* if this cache isn't initialized yet, no need to do anything */
1357 if (!PointerIsValid(SysCache[cacheId]))
1360 CatCacheInvalidate(SysCache[cacheId], hashValue);
1364 * Certain relations that do not have system caches send snapshot invalidation
1365 * messages in lieu of catcache messages. This is for the benefit of
1366 * GetCatalogSnapshot(), which can then reuse its existing MVCC snapshot
1367 * for scanning one of those catalogs, rather than taking a new one, if no
1368 * invalidation has been received.
1370 * Relations that have syscaches need not (and must not) be listed here. The
1371 * catcache invalidation messages will also flush the snapshot. If you add a
1372 * syscache for one of these relations, remove it from this list.
1375 RelationInvalidatesSnapshotsOnly(Oid relid)
1379 case DbRoleSettingRelationId:
1380 case DependRelationId:
1381 case SharedDependRelationId:
1382 case DescriptionRelationId:
1383 case SharedDescriptionRelationId:
1384 case SecLabelRelationId:
1385 case SharedSecLabelRelationId:
1395 * Test whether a relation has a system cache.
1398 RelationHasSysCache(Oid relid)
1401 high = SysCacheRelationOidSize - 1;
1405 int middle = low + (high - low) / 2;
1407 if (SysCacheRelationOid[middle] == relid)
1409 if (SysCacheRelationOid[middle] < relid)
1419 * Test whether a relation supports a system cache, ie it is either a
1420 * cached table or the index used for a cache.
1423 RelationSupportsSysCache(Oid relid)
1426 high = SysCacheSupportingRelOidSize - 1;
1430 int middle = low + (high - low) / 2;
1432 if (SysCacheSupportingRelOid[middle] == relid)
1434 if (SysCacheSupportingRelOid[middle] < relid)
1445 * OID comparator for pg_qsort
1448 oid_compare(const void *a, const void *b)
1450 Oid oa = *((const Oid *) a);
1451 Oid ob = *((const Oid *) b);
1455 return (oa > ob) ? 1 : -1;