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  {RangeRelationId, /* RANGETYPE */
611  1,
612  {
614  0,
615  0,
616  0
617  },
618  4
619  },
620  {RelationRelationId, /* RELNAMENSP */
622  2,
623  {
626  0,
627  0
628  },
629  128
630  },
631  {RelationRelationId, /* RELOID */
633  1,
634  {
636  0,
637  0,
638  0
639  },
640  128
641  },
642  {ReplicationOriginRelationId, /* REPLORIGIDENT */
644  1,
645  {
647  0,
648  0,
649  0
650  },
651  16
652  },
653  {ReplicationOriginRelationId, /* REPLORIGNAME */
655  1,
656  {
658  0,
659  0,
660  0
661  },
662  16
663  },
664  {PublicationRelationId, /* PUBLICATIONOID */
666  1,
667  {
669  0,
670  0,
671  0
672  },
673  8
674  },
675  {PublicationRelationId, /* PUBLICATIONNAME */
677  1,
678  {
680  0,
681  0,
682  0
683  },
684  8
685  },
686  {PublicationRelRelationId, /* PUBLICATIONREL */
688  1,
689  {
691  0,
692  0,
693  0
694  },
695  64
696  },
697  {PublicationRelRelationId, /* PUBLICATIONRELMAP */
699  2,
700  {
703  0,
704  0
705  },
706  64
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, /* SUBSCRIPTIONOID */
765  1,
766  {
768  0,
769  0,
770  0
771  },
772  4
773  },
774  {SubscriptionRelationId, /* SUBSCRIPTIONNAME */
776  2,
777  {
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 
974 #define SysCacheSize ((int) lengthof(cacheinfo))
975 
977 
978 static bool CacheInitialized = false;
979 
980 /* Sorted array of OIDs of tables that have caches on them */
983 
984 /* Sorted array of OIDs of tables and indexes used by caches */
987 
988 static int oid_compare(const void *a, const void *b);
989 
990 
991 /*
992  * InitCatalogCache - initialize the caches
993  *
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
997  * of that cache.
998  */
999 void
1001 {
1002  int cacheId;
1003  int i,
1004  j;
1005 
1007 
1009 
1010  for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
1011  {
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 */
1023  cacheinfo[cacheId].reloid;
1025  cacheinfo[cacheId].reloid;
1027  cacheinfo[cacheId].indoid;
1028  /* see comments for RelationInvalidatesSnapshotsOnly */
1029  Assert(!RelationInvalidatesSnapshotsOnly(cacheinfo[cacheId].reloid));
1030  }
1031 
1034 
1035  /* Sort and de-dup OID arrays, so we can use binary search. */
1037  sizeof(Oid), oid_compare);
1038  for (i = 1, j = 0; i < SysCacheRelationOidSize; i++)
1039  {
1042  }
1043  SysCacheRelationOidSize = j + 1;
1044 
1046  sizeof(Oid), oid_compare);
1047  for (i = 1, j = 0; i < SysCacheSupportingRelOidSize; i++)
1048  {
1051  }
1052  SysCacheSupportingRelOidSize = j + 1;
1053 
1054  CacheInitialized = true;
1055 }
1056 
1057 /*
1058  * InitCatalogCachePhase2 - finish initializing the caches
1059  *
1060  * Finish initializing all the caches, including necessary database
1061  * access.
1062  *
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
1067  * init file.
1068  */
1069 void
1071 {
1072  int cacheId;
1073 
1075 
1076  for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
1077  InitCatCachePhase2(SysCache[cacheId], true);
1078 }
1079 
1080 
1081 /*
1082  * SearchSysCache
1083  *
1084  * A layer on top of SearchCatCache that does the initialization and
1085  * key-setting for you.
1086  *
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!
1089  *
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.
1094  *
1095  * CAUTION: The tuple that is returned must NOT be freed by the caller!
1096  */
1097 HeapTuple
1098 SearchSysCache(int cacheId,
1099  Datum key1,
1100  Datum key2,
1101  Datum key3,
1102  Datum key4)
1103 {
1104  if (cacheId < 0 || cacheId >= SysCacheSize ||
1105  !PointerIsValid(SysCache[cacheId]))
1106  elog(ERROR, "invalid cache ID: %d", cacheId);
1107 
1108  return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
1109 }
1110 
1111 /*
1112  * ReleaseSysCache
1113  * Release previously grabbed reference count on a tuple
1114  */
1115 void
1117 {
1118  ReleaseCatCache(tuple);
1119 }
1120 
1121 /*
1122  * SearchSysCacheCopy
1123  *
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.
1128  */
1129 HeapTuple
1131  Datum key1,
1132  Datum key2,
1133  Datum key3,
1134  Datum key4)
1135 {
1136  HeapTuple tuple,
1137  newtuple;
1138 
1139  tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1140  if (!HeapTupleIsValid(tuple))
1141  return tuple;
1142  newtuple = heap_copytuple(tuple);
1143  ReleaseSysCache(tuple);
1144  return newtuple;
1145 }
1146 
1147 /*
1148  * SearchSysCacheExists
1149  *
1150  * A convenience routine that just probes to see if a tuple can be found.
1151  * No lock is retained on the syscache entry.
1152  */
1153 bool
1155  Datum key1,
1156  Datum key2,
1157  Datum key3,
1158  Datum key4)
1159 {
1160  HeapTuple tuple;
1161 
1162  tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1163  if (!HeapTupleIsValid(tuple))
1164  return false;
1165  ReleaseSysCache(tuple);
1166  return true;
1167 }
1168 
1169 /*
1170  * GetSysCacheOid
1171  *
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.
1175  */
1176 Oid
1177 GetSysCacheOid(int cacheId,
1178  Datum key1,
1179  Datum key2,
1180  Datum key3,
1181  Datum key4)
1182 {
1183  HeapTuple tuple;
1184  Oid result;
1185 
1186  tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1187  if (!HeapTupleIsValid(tuple))
1188  return InvalidOid;
1189  result = HeapTupleGetOid(tuple);
1190  ReleaseSysCache(tuple);
1191  return result;
1192 }
1193 
1194 
1195 /*
1196  * SearchSysCacheAttName
1197  *
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.
1202  */
1203 HeapTuple
1204 SearchSysCacheAttName(Oid relid, const char *attname)
1205 {
1206  HeapTuple tuple;
1207 
1208  tuple = SearchSysCache2(ATTNAME,
1209  ObjectIdGetDatum(relid),
1210  CStringGetDatum(attname));
1211  if (!HeapTupleIsValid(tuple))
1212  return NULL;
1213  if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
1214  {
1215  ReleaseSysCache(tuple);
1216  return NULL;
1217  }
1218  return tuple;
1219 }
1220 
1221 /*
1222  * SearchSysCacheCopyAttName
1223  *
1224  * As above, an attisdropped-aware version of SearchSysCacheCopy.
1225  */
1226 HeapTuple
1227 SearchSysCacheCopyAttName(Oid relid, const char *attname)
1228 {
1229  HeapTuple tuple,
1230  newtuple;
1231 
1232  tuple = SearchSysCacheAttName(relid, attname);
1233  if (!HeapTupleIsValid(tuple))
1234  return tuple;
1235  newtuple = heap_copytuple(tuple);
1236  ReleaseSysCache(tuple);
1237  return newtuple;
1238 }
1239 
1240 /*
1241  * SearchSysCacheExistsAttName
1242  *
1243  * As above, an attisdropped-aware version of SearchSysCacheExists.
1244  */
1245 bool
1246 SearchSysCacheExistsAttName(Oid relid, const char *attname)
1247 {
1248  HeapTuple tuple;
1249 
1250  tuple = SearchSysCacheAttName(relid, attname);
1251  if (!HeapTupleIsValid(tuple))
1252  return false;
1253  ReleaseSysCache(tuple);
1254  return true;
1255 }
1256 
1257 
1258 /*
1259  * SysCacheGetAttr
1260  *
1261  * Given a tuple previously fetched by SearchSysCache(),
1262  * extract a specific attribute.
1263  *
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/.
1269  *
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!
1273  *
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.
1276  */
1277 Datum
1278 SysCacheGetAttr(int cacheId, HeapTuple tup,
1279  AttrNumber attributeNumber,
1280  bool *isNull)
1281 {
1282  /*
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.
1287  */
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))
1292  {
1293  InitCatCachePhase2(SysCache[cacheId], false);
1294  Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
1295  }
1296 
1297  return heap_getattr(tup, attributeNumber,
1298  SysCache[cacheId]->cc_tupdesc,
1299  isNull);
1300 }
1301 
1302 /*
1303  * GetSysCacheHashValue
1304  *
1305  * Get the hash value that would be used for a tuple in the specified cache
1306  * with the given search keys.
1307  *
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.
1311  */
1312 uint32
1314  Datum key1,
1315  Datum key2,
1316  Datum key3,
1317  Datum key4)
1318 {
1319  if (cacheId < 0 || cacheId >= SysCacheSize ||
1320  !PointerIsValid(SysCache[cacheId]))
1321  elog(ERROR, "invalid cache ID: %d", cacheId);
1322 
1323  return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
1324 }
1325 
1326 /*
1327  * List-search interface
1328  */
1329 struct catclist *
1330 SearchSysCacheList(int cacheId, int nkeys,
1331  Datum key1, Datum key2, Datum key3, Datum key4)
1332 {
1333  if (cacheId < 0 || cacheId >= SysCacheSize ||
1334  !PointerIsValid(SysCache[cacheId]))
1335  elog(ERROR, "invalid cache ID: %d", cacheId);
1336 
1337  return SearchCatCacheList(SysCache[cacheId], nkeys,
1338  key1, key2, key3, key4);
1339 }
1340 
1341 /*
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.
1347  *
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.
1351  */
1352 bool
1354 {
1355  switch (relid)
1356  {
1358  case DependRelationId:
1360  case DescriptionRelationId:
1362  case SecLabelRelationId:
1364  return true;
1365  default:
1366  break;
1367  }
1368 
1369  return false;
1370 }
1371 
1372 /*
1373  * Test whether a relation has a system cache.
1374  */
1375 bool
1377 {
1378  int low = 0,
1379  high = SysCacheRelationOidSize - 1;
1380 
1381  while (low <= high)
1382  {
1383  int middle = low + (high - low) / 2;
1384 
1385  if (SysCacheRelationOid[middle] == relid)
1386  return true;
1387  if (SysCacheRelationOid[middle] < relid)
1388  low = middle + 1;
1389  else
1390  high = middle - 1;
1391  }
1392 
1393  return false;
1394 }
1395 
1396 /*
1397  * Test whether a relation supports a system cache, ie it is either a
1398  * cached table or the index used for a cache.
1399  */
1400 bool
1402 {
1403  int low = 0,
1404  high = SysCacheSupportingRelOidSize - 1;
1405 
1406  while (low <= high)
1407  {
1408  int middle = low + (high - low) / 2;
1409 
1410  if (SysCacheSupportingRelOid[middle] == relid)
1411  return true;
1412  if (SysCacheSupportingRelOid[middle] < relid)
1413  low = middle + 1;
1414  else
1415  high = middle - 1;
1416  }
1417 
1418  return false;
1419 }
1420 
1421 
1422 /*
1423  * OID comparator for pg_qsort
1424  */
1425 static int
1426 oid_compare(const void *a, const void *b)
1427 {
1428  Oid oa = *((const Oid *) a);
1429  Oid ob = *((const Oid *) b);
1430 
1431  if (oa == ob)
1432  return 0;
1433  return (oa > ob) ? 1 : -1;
1434 }
HeapTuple SearchSysCache(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:1098
#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:192
#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:978
#define Anum_pg_operator_oprleft
Definition: pg_operator.h:71
bool RelationHasSysCache(Oid relid)
Definition: syscache.c:1376
#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:986
#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:1330
#define TransformRelationId
Definition: pg_transform.h:25
#define Anum_pg_user_mapping_umuser
#define Anum_pg_attribute_attnum
Definition: pg_attribute.h:197
#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:985
#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:1618
#define ClassNameNspIndexId
Definition: indexing.h:114
static int SysCacheRelationOidSize
Definition: syscache.c:982
#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:1177
#define TypeRelationId
Definition: pg_type.h:34
#define Anum_pg_ts_config_map_maptokentype
#define Anum_pg_collation_collnamespace
Definition: pg_collation.h:59
#define Anum_pg_type_typnamespace
Definition: pg_type.h:241
bool SearchSysCacheExistsAttName(Oid relid, const char *attname)
Definition: syscache.c:1246
#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:1154
#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 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 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_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:1227
#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 SysCacheSize
Definition: syscache.c:974
#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:184
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:719
#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:58
#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:976
#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:1116
#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:1278
static Oid SysCacheRelationOid[SysCacheSize]
Definition: syscache.c:981
#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:1317
#define RewriteRelationId
Definition: pg_rewrite.h:32
uint32 GetSysCacheHashValue(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:1313
#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 Anum_pg_statistic_ext_stanamespace
#define Assert(condition)
Definition: c.h:675
#define Anum_pg_statistic_ext_staname
#define Anum_pg_proc_pronamespace
Definition: pg_proc.h:91
bool RelationInvalidatesSnapshotsOnly(Oid relid)
Definition: syscache.c:1353
#define StatisticExtRelationId
#define ForeignDataWrapperOidIndexId
Definition: indexing.h:287
#define EventTriggerRelationId
#define StatisticRelidAttnumInhIndexId
Definition: indexing.h:234
#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_ts_parser_prsnamespace
Definition: pg_ts_parser.h:52
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1204
#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:1130
#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:1000
#define Anum_pg_default_acl_defaclobjtype
HeapTuple SearchCatCache(CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1103
#define SubscriptionNameIndexId
Definition: indexing.h:357
static int oid_compare(const void *a, const void *b)
Definition: syscache.c:1426
#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:1389
#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:62
#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:988
#define Anum_pg_publication_pubname
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
bool RelationSupportsSysCache(Oid relid)
Definition: syscache.c:1401
uint32 GetCatCacheHashValue(CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1349
#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:1070
#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:193
#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:154