PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
syscache.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * syscache.c
4  * System cache management routines
5  *
6  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/utils/cache/syscache.c
12  *
13  * NOTES
14  * These routines allow the parser/planner/executor to perform
15  * rapid lookups on the contents of the system catalogs.
16  *
17  * see utils/syscache.h for a list of the cache IDs
18  *
19  *-------------------------------------------------------------------------
20  */
21 #include "postgres.h"
22 
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"
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"
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"
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"
52 #include "catalog/pg_proc.h"
53 #include "catalog/pg_publication.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"
61 #include "catalog/pg_shseclabel.h"
63 #include "catalog/pg_statistic.h"
67 #include "catalog/pg_tablespace.h"
68 #include "catalog/pg_transform.h"
69 #include "catalog/pg_ts_config.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"
76 #include "utils/rel.h"
77 #include "utils/catcache.h"
78 #include "utils/syscache.h"
79 
80 
81 /*---------------------------------------------------------------------------
82 
83  Adding system caches:
84 
85  Add your new cache to the list in include/utils/syscache.h.
86  Keep the list sorted alphabetically.
87 
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
91  hash buckets.
92 
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.
96 
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.)
103 
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.
107 
108 *---------------------------------------------------------------------------
109 */
110 
111 /*
112  * struct cachedesc: information defining a single syscache
113  */
114 struct cachedesc
115 {
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 */
121 };
122 
123 static const struct cachedesc cacheinfo[] = {
124  {AggregateRelationId, /* AGGFNOID */
126  1,
127  {
129  0,
130  0,
131  0
132  },
133  16
134  },
135  {AccessMethodRelationId, /* AMNAME */
137  1,
138  {
140  0,
141  0,
142  0
143  },
144  4
145  },
146  {AccessMethodRelationId, /* AMOID */
147  AmOidIndexId,
148  1,
149  {
151  0,
152  0,
153  0
154  },
155  4
156  },
157  {AccessMethodOperatorRelationId, /* AMOPOPID */
159  3,
160  {
164  0
165  },
166  64
167  },
168  {AccessMethodOperatorRelationId, /* AMOPSTRATEGY */
170  4,
171  {
176  },
177  64
178  },
179  {AccessMethodProcedureRelationId, /* AMPROCNUM */
181  4,
182  {
187  },
188  16
189  },
190  {AttributeRelationId, /* ATTNAME */
192  2,
193  {
196  0,
197  0
198  },
199  32
200  },
201  {AttributeRelationId, /* ATTNUM */
203  2,
204  {
207  0,
208  0
209  },
210  128
211  },
212  {AuthMemRelationId, /* AUTHMEMMEMROLE */
214  2,
215  {
218  0,
219  0
220  },
221  8
222  },
223  {AuthMemRelationId, /* AUTHMEMROLEMEM */
225  2,
226  {
229  0,
230  0
231  },
232  8
233  },
234  {AuthIdRelationId, /* AUTHNAME */
236  1,
237  {
239  0,
240  0,
241  0
242  },
243  8
244  },
245  {AuthIdRelationId, /* AUTHOID */
247  1,
248  {
250  0,
251  0,
252  0
253  },
254  8
255  },
256  {
257  CastRelationId, /* CASTSOURCETARGET */
259  2,
260  {
263  0,
264  0
265  },
266  256
267  },
268  {OperatorClassRelationId, /* CLAAMNAMENSP */
270  3,
271  {
275  0
276  },
277  8
278  },
279  {OperatorClassRelationId, /* CLAOID */
281  1,
282  {
284  0,
285  0,
286  0
287  },
288  8
289  },
290  {CollationRelationId, /* COLLNAMEENCNSP */
292  3,
293  {
297  0
298  },
299  8
300  },
301  {CollationRelationId, /* COLLOID */
303  1,
304  {
306  0,
307  0,
308  0
309  },
310  8
311  },
312  {ConversionRelationId, /* CONDEFAULT */
314  4,
315  {
320  },
321  8
322  },
323  {ConversionRelationId, /* CONNAMENSP */
325  2,
326  {
329  0,
330  0
331  },
332  8
333  },
334  {ConstraintRelationId, /* CONSTROID */
336  1,
337  {
339  0,
340  0,
341  0
342  },
343  16
344  },
345  {ConversionRelationId, /* CONVOID */
347  1,
348  {
350  0,
351  0,
352  0
353  },
354  8
355  },
356  {DatabaseRelationId, /* DATABASEOID */
358  1,
359  {
361  0,
362  0,
363  0
364  },
365  4
366  },
367  {DefaultAclRelationId, /* DEFACLROLENSPOBJ */
369  3,
370  {
374  0
375  },
376  8
377  },
378  {EnumRelationId, /* ENUMOID */
380  1,
381  {
383  0,
384  0,
385  0
386  },
387  8
388  },
389  {EnumRelationId, /* ENUMTYPOIDNAME */
391  2,
392  {
395  0,
396  0
397  },
398  8
399  },
400  {EventTriggerRelationId, /* EVENTTRIGGERNAME */
402  1,
403  {
405  0,
406  0,
407  0
408  },
409  8
410  },
411  {EventTriggerRelationId, /* EVENTTRIGGEROID */
413  1,
414  {
416  0,
417  0,
418  0
419  },
420  8
421  },
422  {ForeignDataWrapperRelationId, /* FOREIGNDATAWRAPPERNAME */
424  1,
425  {
427  0,
428  0,
429  0
430  },
431  2
432  },
433  {ForeignDataWrapperRelationId, /* FOREIGNDATAWRAPPEROID */
435  1,
436  {
438  0,
439  0,
440  0
441  },
442  2
443  },
444  {ForeignServerRelationId, /* FOREIGNSERVERNAME */
446  1,
447  {
449  0,
450  0,
451  0
452  },
453  2
454  },
455  {ForeignServerRelationId, /* FOREIGNSERVEROID */
457  1,
458  {
460  0,
461  0,
462  0
463  },
464  2
465  },
466  {ForeignTableRelationId, /* FOREIGNTABLEREL */
468  1,
469  {
471  0,
472  0,
473  0
474  },
475  4
476  },
477  {IndexRelationId, /* INDEXRELID */
479  1,
480  {
482  0,
483  0,
484  0
485  },
486  64
487  },
488  {LanguageRelationId, /* LANGNAME */
490  1,
491  {
493  0,
494  0,
495  0
496  },
497  4
498  },
499  {LanguageRelationId, /* LANGOID */
501  1,
502  {
504  0,
505  0,
506  0
507  },
508  4
509  },
510  {NamespaceRelationId, /* NAMESPACENAME */
512  1,
513  {
515  0,
516  0,
517  0
518  },
519  4
520  },
521  {NamespaceRelationId, /* NAMESPACEOID */
523  1,
524  {
526  0,
527  0,
528  0
529  },
530  16
531  },
532  {OperatorRelationId, /* OPERNAMENSP */
534  4,
535  {
540  },
541  256
542  },
543  {OperatorRelationId, /* OPEROID */
545  1,
546  {
548  0,
549  0,
550  0
551  },
552  32
553  },
554  {OperatorFamilyRelationId, /* OPFAMILYAMNAMENSP */
556  3,
557  {
561  0
562  },
563  8
564  },
565  {OperatorFamilyRelationId, /* OPFAMILYOID */
567  1,
568  {
570  0,
571  0,
572  0
573  },
574  8
575  },
576  {PartitionedRelationId, /* PARTRELID */
578  1,
579  {
581  0,
582  0,
583  0
584  },
585  32
586  },
587  {ProcedureRelationId, /* PROCNAMEARGSNSP */
589  3,
590  {
594  0
595  },
596  128
597  },
598  {ProcedureRelationId, /* PROCOID */
600  1,
601  {
603  0,
604  0,
605  0
606  },
607  128
608  },
609  {PublicationRelationId, /* PUBLICATIONNAME */
611  1,
612  {
614  0,
615  0,
616  0
617  },
618  8
619  },
620  {PublicationRelationId, /* PUBLICATIONOID */
622  1,
623  {
625  0,
626  0,
627  0
628  },
629  8
630  },
631  {PublicationRelRelationId, /* PUBLICATIONREL */
633  1,
634  {
636  0,
637  0,
638  0
639  },
640  64
641  },
642  {PublicationRelRelationId, /* PUBLICATIONRELMAP */
644  2,
645  {
648  0,
649  0
650  },
651  64
652  },
653  {RangeRelationId, /* RANGETYPE */
655  1,
656  {
658  0,
659  0,
660  0
661  },
662  4
663  },
664  {RelationRelationId, /* RELNAMENSP */
666  2,
667  {
670  0,
671  0
672  },
673  128
674  },
675  {RelationRelationId, /* RELOID */
677  1,
678  {
680  0,
681  0,
682  0
683  },
684  128
685  },
686  {ReplicationOriginRelationId, /* REPLORIGIDENT */
688  1,
689  {
691  0,
692  0,
693  0
694  },
695  16
696  },
697  {ReplicationOriginRelationId, /* REPLORIGNAME */
699  1,
700  {
702  0,
703  0,
704  0
705  },
706  16
707  },
708  {RewriteRelationId, /* RULERELNAME */
710  2,
711  {
714  0,
715  0
716  },
717  8
718  },
719  {SequenceRelationId, /* SEQRELID */
721  1,
722  {
724  0,
725  0,
726  0
727  },
728  32
729  },
730  {StatisticExtRelationId, /* STATEXTNAMENSP */
732  2,
733  {
736  0,
737  0
738  },
739  4
740  },
741  {StatisticExtRelationId, /* STATEXTOID */
743  1,
744  {
746  0,
747  0,
748  0
749  },
750  4
751  },
752  {StatisticRelationId, /* STATRELATTINH */
754  3,
755  {
759  0
760  },
761  128
762  },
763  {SubscriptionRelationId, /* SUBSCRIPTIONNAME */
765  2,
766  {
769  0,
770  0
771  },
772  4
773  },
774  {SubscriptionRelationId, /* SUBSCRIPTIONOID */
776  1,
777  {
779  0,
780  0,
781  0
782  },
783  4
784  },
785  {SubscriptionRelRelationId, /* SUBSCRIPTIONRELMAP */
787  2,
788  {
791  0,
792  0
793  },
794  64
795  },
796  {TableSpaceRelationId, /* TABLESPACEOID */
798  1,
799  {
801  0,
802  0,
803  0,
804  },
805  4
806  },
807  {TransformRelationId, /* TRFOID */
809  1,
810  {
812  0,
813  0,
814  0,
815  },
816  16
817  },
818  {TransformRelationId, /* TRFTYPELANG */
820  2,
821  {
824  0,
825  0,
826  },
827  16
828  },
829  {TSConfigMapRelationId, /* TSCONFIGMAP */
831  3,
832  {
836  0
837  },
838  2
839  },
840  {TSConfigRelationId, /* TSCONFIGNAMENSP */
842  2,
843  {
846  0,
847  0
848  },
849  2
850  },
851  {TSConfigRelationId, /* TSCONFIGOID */
853  1,
854  {
856  0,
857  0,
858  0
859  },
860  2
861  },
862  {TSDictionaryRelationId, /* TSDICTNAMENSP */
864  2,
865  {
868  0,
869  0
870  },
871  2
872  },
873  {TSDictionaryRelationId, /* TSDICTOID */
875  1,
876  {
878  0,
879  0,
880  0
881  },
882  2
883  },
884  {TSParserRelationId, /* TSPARSERNAMENSP */
886  2,
887  {
890  0,
891  0
892  },
893  2
894  },
895  {TSParserRelationId, /* TSPARSEROID */
897  1,
898  {
900  0,
901  0,
902  0
903  },
904  2
905  },
906  {TSTemplateRelationId, /* TSTEMPLATENAMENSP */
908  2,
909  {
912  0,
913  0
914  },
915  2
916  },
917  {TSTemplateRelationId, /* TSTEMPLATEOID */
919  1,
920  {
922  0,
923  0,
924  0
925  },
926  2
927  },
928  {TypeRelationId, /* TYPENAMENSP */
930  2,
931  {
934  0,
935  0
936  },
937  64
938  },
939  {TypeRelationId, /* TYPEOID */
941  1,
942  {
944  0,
945  0,
946  0
947  },
948  64
949  },
950  {UserMappingRelationId, /* USERMAPPINGOID */
952  1,
953  {
955  0,
956  0,
957  0
958  },
959  2
960  },
961  {UserMappingRelationId, /* USERMAPPINGUSERSERVER */
963  2,
964  {
967  0,
968  0
969  },
970  2
971  }
972 };
973 
975 
976 static bool CacheInitialized = false;
977 
978 /* Sorted array of OIDs of tables that have caches on them */
981 
982 /* Sorted array of OIDs of tables and indexes used by caches */
985 
986 static int oid_compare(const void *a, const void *b);
987 
988 
989 /*
990  * InitCatalogCache - initialize the caches
991  *
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
995  * of that cache.
996  */
997 void
999 {
1000  int cacheId;
1001  int i,
1002  j;
1003 
1004  StaticAssertStmt(SysCacheSize == (int) lengthof(cacheinfo),
1005  "SysCacheSize does not match syscache.c's array");
1006 
1008 
1010 
1011  for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
1012  {
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 */
1024  cacheinfo[cacheId].reloid;
1026  cacheinfo[cacheId].reloid;
1028  cacheinfo[cacheId].indoid;
1029  /* see comments for RelationInvalidatesSnapshotsOnly */
1030  Assert(!RelationInvalidatesSnapshotsOnly(cacheinfo[cacheId].reloid));
1031  }
1032 
1035 
1036  /* Sort and de-dup OID arrays, so we can use binary search. */
1038  sizeof(Oid), oid_compare);
1039  for (i = 1, j = 0; i < SysCacheRelationOidSize; i++)
1040  {
1043  }
1044  SysCacheRelationOidSize = j + 1;
1045 
1047  sizeof(Oid), oid_compare);
1048  for (i = 1, j = 0; i < SysCacheSupportingRelOidSize; i++)
1049  {
1052  }
1053  SysCacheSupportingRelOidSize = j + 1;
1054 
1055  CacheInitialized = true;
1056 }
1057 
1058 /*
1059  * InitCatalogCachePhase2 - finish initializing the caches
1060  *
1061  * Finish initializing all the caches, including necessary database
1062  * access.
1063  *
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
1068  * init file.
1069  */
1070 void
1072 {
1073  int cacheId;
1074 
1076 
1077  for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
1078  InitCatCachePhase2(SysCache[cacheId], true);
1079 }
1080 
1081 
1082 /*
1083  * SearchSysCache
1084  *
1085  * A layer on top of SearchCatCache that does the initialization and
1086  * key-setting for you.
1087  *
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!
1090  *
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.
1095  *
1096  * CAUTION: The tuple that is returned must NOT be freed by the caller!
1097  */
1098 HeapTuple
1099 SearchSysCache(int cacheId,
1100  Datum key1,
1101  Datum key2,
1102  Datum key3,
1103  Datum key4)
1104 {
1105  if (cacheId < 0 || cacheId >= SysCacheSize ||
1106  !PointerIsValid(SysCache[cacheId]))
1107  elog(ERROR, "invalid cache ID: %d", cacheId);
1108 
1109  return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
1110 }
1111 
1112 /*
1113  * ReleaseSysCache
1114  * Release previously grabbed reference count on a tuple
1115  */
1116 void
1118 {
1119  ReleaseCatCache(tuple);
1120 }
1121 
1122 /*
1123  * SearchSysCacheCopy
1124  *
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.
1129  */
1130 HeapTuple
1132  Datum key1,
1133  Datum key2,
1134  Datum key3,
1135  Datum key4)
1136 {
1137  HeapTuple tuple,
1138  newtuple;
1139 
1140  tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1141  if (!HeapTupleIsValid(tuple))
1142  return tuple;
1143  newtuple = heap_copytuple(tuple);
1144  ReleaseSysCache(tuple);
1145  return newtuple;
1146 }
1147 
1148 /*
1149  * SearchSysCacheExists
1150  *
1151  * A convenience routine that just probes to see if a tuple can be found.
1152  * No lock is retained on the syscache entry.
1153  */
1154 bool
1156  Datum key1,
1157  Datum key2,
1158  Datum key3,
1159  Datum key4)
1160 {
1161  HeapTuple tuple;
1162 
1163  tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1164  if (!HeapTupleIsValid(tuple))
1165  return false;
1166  ReleaseSysCache(tuple);
1167  return true;
1168 }
1169 
1170 /*
1171  * GetSysCacheOid
1172  *
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.
1176  */
1177 Oid
1178 GetSysCacheOid(int cacheId,
1179  Datum key1,
1180  Datum key2,
1181  Datum key3,
1182  Datum key4)
1183 {
1184  HeapTuple tuple;
1185  Oid result;
1186 
1187  tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1188  if (!HeapTupleIsValid(tuple))
1189  return InvalidOid;
1190  result = HeapTupleGetOid(tuple);
1191  ReleaseSysCache(tuple);
1192  return result;
1193 }
1194 
1195 
1196 /*
1197  * SearchSysCacheAttName
1198  *
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.
1203  */
1204 HeapTuple
1205 SearchSysCacheAttName(Oid relid, const char *attname)
1206 {
1207  HeapTuple tuple;
1208 
1209  tuple = SearchSysCache2(ATTNAME,
1210  ObjectIdGetDatum(relid),
1211  CStringGetDatum(attname));
1212  if (!HeapTupleIsValid(tuple))
1213  return NULL;
1214  if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
1215  {
1216  ReleaseSysCache(tuple);
1217  return NULL;
1218  }
1219  return tuple;
1220 }
1221 
1222 /*
1223  * SearchSysCacheCopyAttName
1224  *
1225  * As above, an attisdropped-aware version of SearchSysCacheCopy.
1226  */
1227 HeapTuple
1228 SearchSysCacheCopyAttName(Oid relid, const char *attname)
1229 {
1230  HeapTuple tuple,
1231  newtuple;
1232 
1233  tuple = SearchSysCacheAttName(relid, attname);
1234  if (!HeapTupleIsValid(tuple))
1235  return tuple;
1236  newtuple = heap_copytuple(tuple);
1237  ReleaseSysCache(tuple);
1238  return newtuple;
1239 }
1240 
1241 /*
1242  * SearchSysCacheExistsAttName
1243  *
1244  * As above, an attisdropped-aware version of SearchSysCacheExists.
1245  */
1246 bool
1247 SearchSysCacheExistsAttName(Oid relid, const char *attname)
1248 {
1249  HeapTuple tuple;
1250 
1251  tuple = SearchSysCacheAttName(relid, attname);
1252  if (!HeapTupleIsValid(tuple))
1253  return false;
1254  ReleaseSysCache(tuple);
1255  return true;
1256 }
1257 
1258 
1259 /*
1260  * SysCacheGetAttr
1261  *
1262  * Given a tuple previously fetched by SearchSysCache(),
1263  * extract a specific attribute.
1264  *
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/.
1270  *
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!
1274  *
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.
1277  */
1278 Datum
1279 SysCacheGetAttr(int cacheId, HeapTuple tup,
1280  AttrNumber attributeNumber,
1281  bool *isNull)
1282 {
1283  /*
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.
1288  */
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))
1293  {
1294  InitCatCachePhase2(SysCache[cacheId], false);
1295  Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
1296  }
1297 
1298  return heap_getattr(tup, attributeNumber,
1299  SysCache[cacheId]->cc_tupdesc,
1300  isNull);
1301 }
1302 
1303 /*
1304  * GetSysCacheHashValue
1305  *
1306  * Get the hash value that would be used for a tuple in the specified cache
1307  * with the given search keys.
1308  *
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.
1312  */
1313 uint32
1315  Datum key1,
1316  Datum key2,
1317  Datum key3,
1318  Datum key4)
1319 {
1320  if (cacheId < 0 || cacheId >= SysCacheSize ||
1321  !PointerIsValid(SysCache[cacheId]))
1322  elog(ERROR, "invalid cache ID: %d", cacheId);
1323 
1324  return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
1325 }
1326 
1327 /*
1328  * List-search interface
1329  */
1330 struct catclist *
1331 SearchSysCacheList(int cacheId, int nkeys,
1332  Datum key1, Datum key2, Datum key3, Datum key4)
1333 {
1334  if (cacheId < 0 || cacheId >= SysCacheSize ||
1335  !PointerIsValid(SysCache[cacheId]))
1336  elog(ERROR, "invalid cache ID: %d", cacheId);
1337 
1338  return SearchCatCacheList(SysCache[cacheId], nkeys,
1339  key1, key2, key3, key4);
1340 }
1341 
1342 /*
1343  * SysCacheInvalidate
1344  *
1345  * Invalidate entries in the specified cache, given a hash value.
1346  * See CatCacheInvalidate() for more info.
1347  *
1348  * This routine is only quasi-public: it should only be used by inval.c.
1349  */
1350 void
1351 SysCacheInvalidate(int cacheId, uint32 hashValue)
1352 {
1353  if (cacheId < 0 || cacheId >= SysCacheSize)
1354  elog(ERROR, "invalid cache ID: %d", cacheId);
1355 
1356  /* if this cache isn't initialized yet, no need to do anything */
1357  if (!PointerIsValid(SysCache[cacheId]))
1358  return;
1359 
1360  CatCacheInvalidate(SysCache[cacheId], hashValue);
1361 }
1362 
1363 /*
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.
1369  *
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.
1373  */
1374 bool
1376 {
1377  switch (relid)
1378  {
1380  case DependRelationId:
1382  case DescriptionRelationId:
1384  case SecLabelRelationId:
1386  return true;
1387  default:
1388  break;
1389  }
1390 
1391  return false;
1392 }
1393 
1394 /*
1395  * Test whether a relation has a system cache.
1396  */
1397 bool
1399 {
1400  int low = 0,
1401  high = SysCacheRelationOidSize - 1;
1402 
1403  while (low <= high)
1404  {
1405  int middle = low + (high - low) / 2;
1406 
1407  if (SysCacheRelationOid[middle] == relid)
1408  return true;
1409  if (SysCacheRelationOid[middle] < relid)
1410  low = middle + 1;
1411  else
1412  high = middle - 1;
1413  }
1414 
1415  return false;
1416 }
1417 
1418 /*
1419  * Test whether a relation supports a system cache, ie it is either a
1420  * cached table or the index used for a cache.
1421  */
1422 bool
1424 {
1425  int low = 0,
1426  high = SysCacheSupportingRelOidSize - 1;
1427 
1428  while (low <= high)
1429  {
1430  int middle = low + (high - low) / 2;
1431 
1432  if (SysCacheSupportingRelOid[middle] == relid)
1433  return true;
1434  if (SysCacheSupportingRelOid[middle] < relid)
1435  low = middle + 1;
1436  else
1437  high = middle - 1;
1438  }
1439 
1440  return false;
1441 }
1442 
1443 
1444 /*
1445  * OID comparator for pg_qsort
1446  */
1447 static int
1448 oid_compare(const void *a, const void *b)
1449 {
1450  Oid oa = *((const Oid *) a);
1451  Oid ob = *((const Oid *) b);
1452 
1453  if (oa == ob)
1454  return 0;
1455  return (oa > ob) ? 1 : -1;
1456 }
HeapTuple SearchSysCache(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:1099
#define ConstraintOidIndexId
Definition: indexing.h:130
#define AttributeRelidNumIndexId
Definition: indexing.h:94
#define Anum_pg_event_trigger_evtname
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:608
#define NamespaceOidIndexId
Definition: indexing.h:195
#define ProcedureOidIndexId
Definition: indexing.h:216
#define Anum_pg_attribute_attrelid
Definition: pg_attribute.h:195
#define NamespaceRelationId
Definition: pg_namespace.h:34
#define CollationOidIndexId
Definition: indexing.h:121
#define Anum_pg_opclass_opcmethod
Definition: pg_opclass.h:75
static bool CacheInitialized
Definition: syscache.c:976
#define Anum_pg_operator_oprleft
Definition: pg_operator.h:71
bool RelationHasSysCache(Oid relid)
Definition: syscache.c:1398
#define OperatorRelationId
Definition: pg_operator.h:32
#define Anum_pg_cast_casttarget
Definition: pg_cast.h:79
#define Anum_pg_ts_config_map_mapseqno
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define Anum_pg_subscription_rel_srsubid
#define IndexRelidIndexId
Definition: indexing.h:164
#define Anum_pg_opfamily_opfmethod
Definition: pg_opfamily.h:51
#define Anum_pg_replication_origin_roident
static int SysCacheSupportingRelOidSize
Definition: syscache.c:984
void CatCacheInvalidate(CatCache *cache, uint32 hashValue)
Definition: catcache.c:443
#define SharedDependRelationId
Definition: pg_shdepend.h:29
struct catclist * SearchSysCacheList(int cacheId, int nkeys, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:1331
#define TransformRelationId
Definition: pg_transform.h:25
#define Anum_pg_user_mapping_umuser
#define Anum_pg_attribute_attnum
Definition: pg_attribute.h:200
#define SubscriptionRelRelationId
#define Anum_pg_statistic_stainherit
Definition: pg_statistic.h:138
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define Anum_pg_user_mapping_umserver
#define RewriteRelRulenameIndexId
Definition: indexing.h:223
static Oid SysCacheSupportingRelOid[SysCacheSize *2]
Definition: syscache.c:983
#define ForeignServerNameIndexId
Definition: indexing.h:294
#define Anum_pg_type_typname
Definition: pg_type.h:240
#define ProcedureRelationId
Definition: pg_proc.h:33
#define PublicationNameIndexId
Definition: indexing.h:345
#define AuthMemRelationId
#define IndexRelationId
Definition: pg_index.h:29
#define DatabaseRelationId
Definition: pg_database.h:29
#define RelationRelationId
Definition: pg_class.h:29
#define Anum_pg_conversion_contoencoding
Definition: pg_conversion.h:68
#define CastSourceTargetIndexId
Definition: indexing.h:109
#define DependRelationId
Definition: pg_depend.h:29
#define Anum_pg_opfamily_opfnamespace
Definition: pg_opfamily.h:53
#define OperatorClassRelationId
Definition: pg_opclass.h:49
#define OperatorFamilyRelationId
Definition: pg_opfamily.h:29
#define Anum_pg_rewrite_ev_class
Definition: pg_rewrite.h:61
#define AttributeRelationId
Definition: pg_attribute.h:33
#define Anum_pg_default_acl_defaclrole
#define SequenceRelationId
Definition: pg_sequence.h:6
#define Anum_pg_statistic_staattnum
Definition: pg_statistic.h:137
#define PublicationRelationId
return result
Definition: formatting.c:1633
#define ClassNameNspIndexId
Definition: indexing.h:114
static int SysCacheRelationOidSize
Definition: syscache.c:980
#define Anum_pg_amop_amoprighttype
Definition: pg_amop.h:86
#define AuthIdOidIndexId
Definition: indexing.h:99
#define lengthof(array)
Definition: c.h:562
#define Anum_pg_enum_enumlabel
Definition: pg_enum.h:55
unsigned int Oid
Definition: postgres_ext.h:31
#define Anum_pg_opfamily_opfname
Definition: pg_opfamily.h:52
#define EnumTypIdLabelIndexId
Definition: indexing.h:157
Oid GetSysCacheOid(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:1178
#define TypeRelationId
Definition: pg_type.h:34
#define Anum_pg_ts_config_map_maptokentype
#define Anum_pg_collation_collnamespace
Definition: pg_collation.h:60
#define Anum_pg_type_typnamespace
Definition: pg_type.h:241
bool SearchSysCacheExistsAttName(Oid relid, const char *attname)
Definition: syscache.c:1247
#define OpclassAmNameNspIndexId
Definition: indexing.h:198
#define DefaultAclRelationId
#define AccessMethodOperatorIndexId
Definition: indexing.h:77
#define Anum_pg_class_relnamespace
Definition: pg_class.h:104
short nkeys
Definition: catcache.h:151
#define StatisticExtNameIndexId
Definition: indexing.h:188
#define AggregateFnoidIndexId
Definition: indexing.h:67
#define AccessMethodOperatorRelationId
Definition: pg_amop.h:54
#define Anum_pg_partitioned_table_partrelid
static const struct cachedesc cacheinfo[]
Definition: syscache.c:123
bool SearchSysCacheExists(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:1155
#define AggregateRelationId
Definition: pg_aggregate.h:53
#define AmNameIndexId
Definition: indexing.h:70
#define SubscriptionRelSrrelidSrsubidIndexId
Definition: indexing.h:360
#define TSDictionaryOidIndexId
Definition: indexing.h:269
#define PublicationRelRelationId
#define AuthIdRelationId
Definition: pg_authid.h:42
Oid reloid
Definition: syscache.c:116
#define Anum_pg_amproc_amproclefttype
Definition: pg_amproc.h:67
#define Anum_pg_foreign_server_srvname
#define Anum_pg_conversion_conforencoding
Definition: pg_conversion.h:67
#define Anum_pg_cast_castsource
Definition: pg_cast.h:78
#define Anum_pg_rewrite_rulename
Definition: pg_rewrite.h:60
#define TSConfigRelationId
Definition: pg_ts_config.h:31
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:758
#define Anum_pg_opclass_opcnamespace
Definition: pg_opclass.h:77
#define ForeignDataWrapperNameIndexId
Definition: indexing.h:289
#define LanguageNameIndexId
Definition: indexing.h:175
#define Anum_pg_replication_origin_roname
#define SysCacheSize
Definition: syscache.h:112
#define TSConfigMapRelationId
#define ReplicationOriginIdentIndex
Definition: indexing.h:333
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define PublicationObjectIndexId
Definition: indexing.h:342
#define Anum_pg_aggregate_aggfnoid
Definition: pg_aggregate.h:95
#define EnumRelationId
Definition: pg_enum.h:32
#define Anum_pg_transform_trflang
Definition: pg_transform.h:43
#define TSDictionaryRelationId
Definition: pg_ts_dict.h:31
#define Anum_pg_statistic_ext_stxnamespace
#define Anum_pg_opclass_opcname
Definition: pg_opclass.h:76
#define Anum_pg_ts_config_map_mapcfg
#define Anum_pg_subscription_subname
#define SequenceRelidIndexId
Definition: indexing.h:226
HeapTuple SearchSysCacheCopyAttName(Oid relid, const char *attname)
Definition: syscache.c:1228
#define Anum_pg_amproc_amprocfamily
Definition: pg_amproc.h:66
#define TablespaceOidIndexId
Definition: indexing.h:237
#define SubscriptionRelationId
#define PartitionedRelidIndexId
Definition: indexing.h:339
#define Anum_pg_ts_config_cfgnamespace
Definition: pg_ts_config.h:49
#define Anum_pg_class_relname
Definition: pg_class.h:103
#define ConversionDefaultIndexId
Definition: indexing.h:133
#define AccessMethodRelationId
Definition: pg_am.h:32
#define PartitionedRelationId
#define Anum_pg_publication_rel_prpubid
#define Anum_pg_publication_rel_prrelid
int nbuckets
Definition: syscache.c:120
#define CStringGetDatum(X)
Definition: postgres.h:584
#define TransformOidIndexId
Definition: indexing.h:242
#define Anum_pg_amproc_amprocnum
Definition: pg_amproc.h:69
#define DatabaseOidIndexId
Definition: indexing.h:142
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
unsigned int uint32
Definition: c.h:268
#define Anum_pg_foreign_data_wrapper_fdwname
#define OperatorNameNspIndexId
Definition: indexing.h:205
#define SharedDescriptionRelationId
#define ClassOidIndexId
Definition: indexing.h:112
#define Anum_pg_ts_template_tmplnamespace
#define Anum_pg_statistic_starelid
Definition: pg_statistic.h:136
CatCache * InitCatCache(int id, Oid reloid, Oid indexoid, int nkeys, const int *key, int nbuckets)
Definition: catcache.c:654
#define Anum_pg_amproc_amprocrighttype
Definition: pg_amproc.h:68
Oid indoid
Definition: syscache.c:117
#define Anum_pg_amop_amoplefttype
Definition: pg_amop.h:85
#define Anum_pg_collation_collname
Definition: pg_collation.h:59
#define Anum_pg_operator_oprright
Definition: pg_operator.h:72
#define Anum_pg_language_lanname
Definition: pg_language.h:58
#define TSConfigOidIndexId
Definition: indexing.h:261
#define Anum_pg_range_rngtypid
Definition: pg_range.h:56
#define AuthMemRoleMemIndexId
Definition: indexing.h:102
#define Anum_pg_subscription_subdbid
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:769
#define SharedSecLabelRelationId
Definition: pg_shseclabel.h:21
#define PublicationRelPrrelidPrpubidIndexId
Definition: indexing.h:351
int nkeys
Definition: syscache.c:118
#define AccessMethodProcedureIndexId
Definition: indexing.h:82
#define Anum_pg_foreign_table_ftrelid
static CatCache * SysCache[SysCacheSize]
Definition: syscache.c:974
#define OpfamilyAmNameNspIndexId
Definition: indexing.h:208
#define OperatorOidIndexId
Definition: indexing.h:203
#define Anum_pg_auth_members_roleid
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
#define SecLabelRelationId
Definition: pg_seclabel.h:21
#define StatisticRelationId
Definition: pg_statistic.h:29
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1279
static Oid SysCacheRelationOid[SysCacheSize]
Definition: syscache.c:979
#define Anum_pg_amop_amoppurpose
Definition: pg_amop.h:88
#define EnumOidIndexId
Definition: indexing.h:155
#define TSParserRelationId
Definition: pg_ts_parser.h:31
#define AttributeRelidNameIndexId
Definition: indexing.h:92
#define CollationRelationId
Definition: pg_collation.h:30
#define TSDictionaryNameNspIndexId
Definition: indexing.h:267
#define TypeNameNspIndexId
Definition: indexing.h:284
#define OpclassOidIndexId
Definition: indexing.h:200
#define InvalidOid
Definition: postgres_ext.h:36
void ReleaseCatCache(HeapTuple tuple)
Definition: catcache.c:1252
#define RewriteRelationId
Definition: pg_rewrite.h:32
uint32 GetSysCacheHashValue(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:1314
#define TSTemplateNameNspIndexId
Definition: indexing.h:277
#define Anum_pg_operator_oprname
Definition: pg_operator.h:65
#define ProcedureNameArgsNspIndexId
Definition: indexing.h:218
#define NamespaceNameIndexId
Definition: indexing.h:193
#define ForeignServerRelationId
#define LanguageOidIndexId
Definition: indexing.h:177
#define Anum_pg_proc_proargtypes
Definition: pg_proc.h:109
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
#define Anum_pg_proc_pronamespace
Definition: pg_proc.h:91
bool RelationInvalidatesSnapshotsOnly(Oid relid)
Definition: syscache.c:1375
#define StatisticExtRelationId
#define ForeignDataWrapperOidIndexId
Definition: indexing.h:287
#define EventTriggerRelationId
#define StatisticRelidAttnumInhIndexId
Definition: indexing.h:234
void SysCacheInvalidate(int cacheId, uint32 hashValue)
Definition: syscache.c:1351
#define AuthMemMemRoleIndexId
Definition: indexing.h:104
#define EventTriggerOidIndexId
Definition: indexing.h:256
int key[4]
Definition: syscache.c:119
#define UserMappingOidIndexId
Definition: indexing.h:297
void pg_qsort(void *base, size_t nel, size_t elsize, int(*cmp)(const void *, const void *))
Definition: qsort.c:113
#define CastRelationId
Definition: pg_cast.h:31
#define ConversionOidIndexId
Definition: indexing.h:137
#define UserMappingUserServerIndexId
Definition: indexing.h:299
#define ForeignDataWrapperRelationId
#define Anum_pg_statistic_ext_stxname
#define Anum_pg_ts_parser_prsnamespace
Definition: pg_ts_parser.h:52
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1205
#define TSParserOidIndexId
Definition: indexing.h:274
#define Anum_pg_conversion_conname
Definition: pg_conversion.h:64
#define CollationNameEncNspIndexId
Definition: indexing.h:119
#define RangeTypidIndexId
Definition: indexing.h:324
#define EventTriggerNameIndexId
Definition: indexing.h:254
#define DescriptionRelationId
#define Anum_pg_default_acl_defaclnamespace
#define TableSpaceRelationId
Definition: pg_tablespace.h:29
#define DefaultAclRoleNspObjIndexId
Definition: indexing.h:305
#define Anum_pg_transform_trftype
Definition: pg_transform.h:42
#define PublicationRelObjectIndexId
Definition: indexing.h:348
#define Anum_pg_authid_rolname
Definition: pg_authid.h:79
#define Anum_pg_ts_dict_dictnamespace
Definition: pg_ts_dict.h:53
#define Anum_pg_operator_oprnamespace
Definition: pg_operator.h:66
HeapTuple SearchSysCacheCopy(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:1131
#define Anum_pg_ts_parser_prsname
Definition: pg_ts_parser.h:51
#define Anum_pg_enum_enumtypid
Definition: pg_enum.h:53
void InitCatalogCache(void)
Definition: syscache.c:998
#define Anum_pg_default_acl_defaclobjtype
HeapTuple SearchCatCache(CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1038
#define SubscriptionNameIndexId
Definition: indexing.h:357
static int oid_compare(const void *a, const void *b)
Definition: syscache.c:1448
#define Anum_pg_am_amname
Definition: pg_am.h:53
#define ReplicationOriginRelationId
#define Anum_pg_amop_amopopr
Definition: pg_amop.h:89
#define Anum_pg_sequence_seqrelid
Definition: pg_sequence.h:23
#define UserMappingRelationId
#define DbRoleSettingRelationId
CatCList * SearchCatCacheList(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1324
#define ForeignTableRelationId
int i
#define RangeRelationId
Definition: pg_range.h:32
#define Anum_pg_amop_amopfamily
Definition: pg_amop.h:84
#define Anum_pg_collation_collencoding
Definition: pg_collation.h:63
#define AccessMethodStrategyIndexId
Definition: indexing.h:75
#define TSConfigMapIndexId
Definition: indexing.h:264
#define ConversionNameNspIndexId
Definition: indexing.h:135
#define LanguageRelationId
Definition: pg_language.h:29
#define Anum_pg_ts_template_tmplname
#define Anum_pg_ts_dict_dictname
Definition: pg_ts_dict.h:52
#define ConstraintRelationId
Definition: pg_constraint.h:29
#define AmOidIndexId
Definition: indexing.h:72
#define StatisticExtOidIndexId
Definition: indexing.h:186
#define ReplicationOriginNameIndex
Definition: indexing.h:336
#define elog
Definition: elog.h:219
void InitCatCachePhase2(CatCache *cache, bool touch_index)
Definition: catcache.c:923
#define Anum_pg_publication_pubname
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
bool RelationSupportsSysCache(Oid relid)
Definition: syscache.c:1423
uint32 GetCatCacheHashValue(CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1284
#define TSTemplateOidIndexId
Definition: indexing.h:279
#define Anum_pg_conversion_connamespace
Definition: pg_conversion.h:65
#define Anum_pg_ts_config_cfgname
Definition: pg_ts_config.h:48
#define AuthIdRolnameIndexId
Definition: indexing.h:97
void InitCatalogCachePhase2(void)
Definition: syscache.c:1071
#define AccessMethodProcedureRelationId
Definition: pg_amproc.h:43
#define PointerIsValid(pointer)
Definition: c.h:526
#define ConversionRelationId
Definition: pg_conversion.h:38
#define ForeignTableRelidIndexId
Definition: indexing.h:302
#define TSParserNameNspIndexId
Definition: indexing.h:272
int16 AttrNumber
Definition: attnum.h:21
#define TSConfigNameNspIndexId
Definition: indexing.h:259
#define TransformTypeLangIndexId
Definition: indexing.h:244
#define Anum_pg_attribute_attname
Definition: pg_attribute.h:196
#define Anum_pg_index_indexrelid
Definition: pg_index.h:74
#define TypeOidIndexId
Definition: indexing.h:282
#define ForeignServerOidIndexId
Definition: indexing.h:292
#define Anum_pg_subscription_rel_srrelid
#define Anum_pg_namespace_nspname
Definition: pg_namespace.h:59
#define Anum_pg_proc_proname
Definition: pg_proc.h:90
#define TSTemplateRelationId
#define OpfamilyOidIndexId
Definition: indexing.h:210
#define Anum_pg_amop_amopstrategy
Definition: pg_amop.h:87
#define SubscriptionObjectIndexId
Definition: indexing.h:354
#define Anum_pg_auth_members_member
#define SearchSysCache2(cacheId, key1, key2)
Definition: syscache.h:158