PostgreSQL Source Code  git master
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-2018, 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  {
128  Anum_pg_aggregate_aggfnoid,
129  0,
130  0,
131  0
132  },
133  16
134  },
135  {AccessMethodRelationId, /* AMNAME */
137  1,
138  {
139  Anum_pg_am_amname,
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  {
161  Anum_pg_amop_amopopr,
162  Anum_pg_amop_amoppurpose,
163  Anum_pg_amop_amopfamily,
164  0
165  },
166  64
167  },
168  {AccessMethodOperatorRelationId, /* AMOPSTRATEGY */
170  4,
171  {
172  Anum_pg_amop_amopfamily,
173  Anum_pg_amop_amoplefttype,
174  Anum_pg_amop_amoprighttype,
175  Anum_pg_amop_amopstrategy
176  },
177  64
178  },
179  {AccessMethodProcedureRelationId, /* AMPROCNUM */
181  4,
182  {
183  Anum_pg_amproc_amprocfamily,
184  Anum_pg_amproc_amproclefttype,
185  Anum_pg_amproc_amprocrighttype,
186  Anum_pg_amproc_amprocnum
187  },
188  16
189  },
190  {AttributeRelationId, /* ATTNAME */
192  2,
193  {
194  Anum_pg_attribute_attrelid,
195  Anum_pg_attribute_attname,
196  0,
197  0
198  },
199  32
200  },
201  {AttributeRelationId, /* ATTNUM */
203  2,
204  {
205  Anum_pg_attribute_attrelid,
206  Anum_pg_attribute_attnum,
207  0,
208  0
209  },
210  128
211  },
212  {AuthMemRelationId, /* AUTHMEMMEMROLE */
214  2,
215  {
216  Anum_pg_auth_members_member,
217  Anum_pg_auth_members_roleid,
218  0,
219  0
220  },
221  8
222  },
223  {AuthMemRelationId, /* AUTHMEMROLEMEM */
225  2,
226  {
227  Anum_pg_auth_members_roleid,
228  Anum_pg_auth_members_member,
229  0,
230  0
231  },
232  8
233  },
234  {AuthIdRelationId, /* AUTHNAME */
236  1,
237  {
238  Anum_pg_authid_rolname,
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  {
261  Anum_pg_cast_castsource,
262  Anum_pg_cast_casttarget,
263  0,
264  0
265  },
266  256
267  },
268  {OperatorClassRelationId, /* CLAAMNAMENSP */
270  3,
271  {
272  Anum_pg_opclass_opcmethod,
273  Anum_pg_opclass_opcname,
274  Anum_pg_opclass_opcnamespace,
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  {
294  Anum_pg_collation_collname,
295  Anum_pg_collation_collencoding,
296  Anum_pg_collation_collnamespace,
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  {
316  Anum_pg_conversion_connamespace,
317  Anum_pg_conversion_conforencoding,
318  Anum_pg_conversion_contoencoding,
320  },
321  8
322  },
323  {ConversionRelationId, /* CONNAMENSP */
325  2,
326  {
327  Anum_pg_conversion_conname,
328  Anum_pg_conversion_connamespace,
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  {
371  Anum_pg_default_acl_defaclrole,
372  Anum_pg_default_acl_defaclnamespace,
373  Anum_pg_default_acl_defaclobjtype,
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  {
393  Anum_pg_enum_enumtypid,
394  Anum_pg_enum_enumlabel,
395  0,
396  0
397  },
398  8
399  },
400  {EventTriggerRelationId, /* EVENTTRIGGERNAME */
402  1,
403  {
404  Anum_pg_event_trigger_evtname,
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  {
426  Anum_pg_foreign_data_wrapper_fdwname,
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  {
448  Anum_pg_foreign_server_srvname,
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  {
470  Anum_pg_foreign_table_ftrelid,
471  0,
472  0,
473  0
474  },
475  4
476  },
477  {IndexRelationId, /* INDEXRELID */
479  1,
480  {
481  Anum_pg_index_indexrelid,
482  0,
483  0,
484  0
485  },
486  64
487  },
488  {LanguageRelationId, /* LANGNAME */
490  1,
491  {
492  Anum_pg_language_lanname,
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  {
514  Anum_pg_namespace_nspname,
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  {
536  Anum_pg_operator_oprname,
537  Anum_pg_operator_oprleft,
538  Anum_pg_operator_oprright,
539  Anum_pg_operator_oprnamespace
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  {
558  Anum_pg_opfamily_opfmethod,
559  Anum_pg_opfamily_opfname,
560  Anum_pg_opfamily_opfnamespace,
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  {
580  Anum_pg_partitioned_table_partrelid,
581  0,
582  0,
583  0
584  },
585  32
586  },
587  {ProcedureRelationId, /* PROCNAMEARGSNSP */
589  3,
590  {
591  Anum_pg_proc_proname,
592  Anum_pg_proc_proargtypes,
593  Anum_pg_proc_pronamespace,
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  {
613  Anum_pg_publication_pubname,
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  {
646  Anum_pg_publication_rel_prrelid,
647  Anum_pg_publication_rel_prpubid,
648  0,
649  0
650  },
651  64
652  },
653  {RangeRelationId, /* RANGETYPE */
655  1,
656  {
657  Anum_pg_range_rngtypid,
658  0,
659  0,
660  0
661  },
662  4
663  },
664  {RelationRelationId, /* RELNAMENSP */
666  2,
667  {
668  Anum_pg_class_relname,
669  Anum_pg_class_relnamespace,
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  {
690  Anum_pg_replication_origin_roident,
691  0,
692  0,
693  0
694  },
695  16
696  },
697  {ReplicationOriginRelationId, /* REPLORIGNAME */
699  1,
700  {
701  Anum_pg_replication_origin_roname,
702  0,
703  0,
704  0
705  },
706  16
707  },
708  {RewriteRelationId, /* RULERELNAME */
710  2,
711  {
712  Anum_pg_rewrite_ev_class,
713  Anum_pg_rewrite_rulename,
714  0,
715  0
716  },
717  8
718  },
719  {SequenceRelationId, /* SEQRELID */
721  1,
722  {
723  Anum_pg_sequence_seqrelid,
724  0,
725  0,
726  0
727  },
728  32
729  },
730  {StatisticExtRelationId, /* STATEXTNAMENSP */
732  2,
733  {
734  Anum_pg_statistic_ext_stxname,
735  Anum_pg_statistic_ext_stxnamespace,
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  {
756  Anum_pg_statistic_starelid,
757  Anum_pg_statistic_staattnum,
758  Anum_pg_statistic_stainherit,
759  0
760  },
761  128
762  },
763  {SubscriptionRelationId, /* SUBSCRIPTIONNAME */
765  2,
766  {
767  Anum_pg_subscription_subdbid,
768  Anum_pg_subscription_subname,
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  {
789  Anum_pg_subscription_rel_srrelid,
790  Anum_pg_subscription_rel_srsubid,
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  {
822  Anum_pg_transform_trftype,
823  Anum_pg_transform_trflang,
824  0,
825  0,
826  },
827  16
828  },
829  {TSConfigMapRelationId, /* TSCONFIGMAP */
831  3,
832  {
833  Anum_pg_ts_config_map_mapcfg,
834  Anum_pg_ts_config_map_maptokentype,
835  Anum_pg_ts_config_map_mapseqno,
836  0
837  },
838  2
839  },
840  {TSConfigRelationId, /* TSCONFIGNAMENSP */
842  2,
843  {
844  Anum_pg_ts_config_cfgname,
845  Anum_pg_ts_config_cfgnamespace,
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  {
866  Anum_pg_ts_dict_dictname,
867  Anum_pg_ts_dict_dictnamespace,
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  {
888  Anum_pg_ts_parser_prsname,
889  Anum_pg_ts_parser_prsnamespace,
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  {
910  Anum_pg_ts_template_tmplname,
911  Anum_pg_ts_template_tmplnamespace,
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  {
932  Anum_pg_type_typname,
933  Anum_pg_type_typnamespace,
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  {
965  Anum_pg_user_mapping_umuser,
966  Anum_pg_user_mapping_umserver,
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  Assert(cacheId >= 0 && cacheId < SysCacheSize &&
1106  PointerIsValid(SysCache[cacheId]));
1107 
1108  return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
1109 }
1110 
1111 HeapTuple
1112 SearchSysCache1(int cacheId,
1113  Datum key1)
1114 {
1115  Assert(cacheId >= 0 && cacheId < SysCacheSize &&
1116  PointerIsValid(SysCache[cacheId]));
1117  Assert(SysCache[cacheId]->cc_nkeys == 1);
1118 
1119  return SearchCatCache1(SysCache[cacheId], key1);
1120 }
1121 
1122 HeapTuple
1123 SearchSysCache2(int cacheId,
1124  Datum key1, Datum key2)
1125 {
1126  Assert(cacheId >= 0 && cacheId < SysCacheSize &&
1127  PointerIsValid(SysCache[cacheId]));
1128  Assert(SysCache[cacheId]->cc_nkeys == 2);
1129 
1130  return SearchCatCache2(SysCache[cacheId], key1, key2);
1131 }
1132 
1133 HeapTuple
1134 SearchSysCache3(int cacheId,
1135  Datum key1, Datum key2, Datum key3)
1136 {
1137  Assert(cacheId >= 0 && cacheId < SysCacheSize &&
1138  PointerIsValid(SysCache[cacheId]));
1139  Assert(SysCache[cacheId]->cc_nkeys == 3);
1140 
1141  return SearchCatCache3(SysCache[cacheId], key1, key2, key3);
1142 }
1143 
1144 HeapTuple
1145 SearchSysCache4(int cacheId,
1146  Datum key1, Datum key2, Datum key3, Datum key4)
1147 {
1148  Assert(cacheId >= 0 && cacheId < SysCacheSize &&
1149  PointerIsValid(SysCache[cacheId]));
1150  Assert(SysCache[cacheId]->cc_nkeys == 4);
1151 
1152  return SearchCatCache4(SysCache[cacheId], key1, key2, key3, key4);
1153 }
1154 
1155 /*
1156  * ReleaseSysCache
1157  * Release previously grabbed reference count on a tuple
1158  */
1159 void
1161 {
1162  ReleaseCatCache(tuple);
1163 }
1164 
1165 /*
1166  * SearchSysCacheCopy
1167  *
1168  * A convenience routine that does SearchSysCache and (if successful)
1169  * returns a modifiable copy of the syscache entry. The original
1170  * syscache entry is released before returning. The caller should
1171  * heap_freetuple() the result when done with it.
1172  */
1173 HeapTuple
1175  Datum key1,
1176  Datum key2,
1177  Datum key3,
1178  Datum key4)
1179 {
1180  HeapTuple tuple,
1181  newtuple;
1182 
1183  tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1184  if (!HeapTupleIsValid(tuple))
1185  return tuple;
1186  newtuple = heap_copytuple(tuple);
1187  ReleaseSysCache(tuple);
1188  return newtuple;
1189 }
1190 
1191 /*
1192  * SearchSysCacheExists
1193  *
1194  * A convenience routine that just probes to see if a tuple can be found.
1195  * No lock is retained on the syscache entry.
1196  */
1197 bool
1199  Datum key1,
1200  Datum key2,
1201  Datum key3,
1202  Datum key4)
1203 {
1204  HeapTuple tuple;
1205 
1206  tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1207  if (!HeapTupleIsValid(tuple))
1208  return false;
1209  ReleaseSysCache(tuple);
1210  return true;
1211 }
1212 
1213 /*
1214  * GetSysCacheOid
1215  *
1216  * A convenience routine that does SearchSysCache and returns the OID
1217  * of the found tuple, or InvalidOid if no tuple could be found.
1218  * No lock is retained on the syscache entry.
1219  */
1220 Oid
1221 GetSysCacheOid(int cacheId,
1222  Datum key1,
1223  Datum key2,
1224  Datum key3,
1225  Datum key4)
1226 {
1227  HeapTuple tuple;
1228  Oid result;
1229 
1230  tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1231  if (!HeapTupleIsValid(tuple))
1232  return InvalidOid;
1233  result = HeapTupleGetOid(tuple);
1234  ReleaseSysCache(tuple);
1235  return result;
1236 }
1237 
1238 
1239 /*
1240  * SearchSysCacheAttName
1241  *
1242  * This routine is equivalent to SearchSysCache on the ATTNAME cache,
1243  * except that it will return NULL if the found attribute is marked
1244  * attisdropped. This is convenient for callers that want to act as
1245  * though dropped attributes don't exist.
1246  */
1247 HeapTuple
1248 SearchSysCacheAttName(Oid relid, const char *attname)
1249 {
1250  HeapTuple tuple;
1251 
1252  tuple = SearchSysCache2(ATTNAME,
1253  ObjectIdGetDatum(relid),
1254  CStringGetDatum(attname));
1255  if (!HeapTupleIsValid(tuple))
1256  return NULL;
1257  if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
1258  {
1259  ReleaseSysCache(tuple);
1260  return NULL;
1261  }
1262  return tuple;
1263 }
1264 
1265 /*
1266  * SearchSysCacheCopyAttName
1267  *
1268  * As above, an attisdropped-aware version of SearchSysCacheCopy.
1269  */
1270 HeapTuple
1272 {
1273  HeapTuple tuple,
1274  newtuple;
1275 
1276  tuple = SearchSysCacheAttName(relid, attname);
1277  if (!HeapTupleIsValid(tuple))
1278  return tuple;
1279  newtuple = heap_copytuple(tuple);
1280  ReleaseSysCache(tuple);
1281  return newtuple;
1282 }
1283 
1284 /*
1285  * SearchSysCacheExistsAttName
1286  *
1287  * As above, an attisdropped-aware version of SearchSysCacheExists.
1288  */
1289 bool
1291 {
1292  HeapTuple tuple;
1293 
1294  tuple = SearchSysCacheAttName(relid, attname);
1295  if (!HeapTupleIsValid(tuple))
1296  return false;
1297  ReleaseSysCache(tuple);
1298  return true;
1299 }
1300 
1301 
1302 /*
1303  * SearchSysCacheAttNum
1304  *
1305  * This routine is equivalent to SearchSysCache on the ATTNUM cache,
1306  * except that it will return NULL if the found attribute is marked
1307  * attisdropped. This is convenient for callers that want to act as
1308  * though dropped attributes don't exist.
1309  */
1310 HeapTuple
1312 {
1313  HeapTuple tuple;
1314 
1315  tuple = SearchSysCache2(ATTNUM,
1316  ObjectIdGetDatum(relid),
1317  Int16GetDatum(attnum));
1318  if (!HeapTupleIsValid(tuple))
1319  return NULL;
1320  if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
1321  {
1322  ReleaseSysCache(tuple);
1323  return NULL;
1324  }
1325  return tuple;
1326 }
1327 
1328 /*
1329  * SearchSysCacheCopyAttNum
1330  *
1331  * As above, an attisdropped-aware version of SearchSysCacheCopy.
1332  */
1333 HeapTuple
1335 {
1336  HeapTuple tuple,
1337  newtuple;
1338 
1339  tuple = SearchSysCacheAttNum(relid, attnum);
1340  if (!HeapTupleIsValid(tuple))
1341  return NULL;
1342  newtuple = heap_copytuple(tuple);
1343  ReleaseSysCache(tuple);
1344  return newtuple;
1345 }
1346 
1347 
1348 /*
1349  * SysCacheGetAttr
1350  *
1351  * Given a tuple previously fetched by SearchSysCache(),
1352  * extract a specific attribute.
1353  *
1354  * This is equivalent to using heap_getattr() on a tuple fetched
1355  * from a non-cached relation. Usually, this is only used for attributes
1356  * that could be NULL or variable length; the fixed-size attributes in
1357  * a system table are accessed just by mapping the tuple onto the C struct
1358  * declarations from include/catalog/.
1359  *
1360  * As with heap_getattr(), if the attribute is of a pass-by-reference type
1361  * then a pointer into the tuple data area is returned --- the caller must
1362  * not modify or pfree the datum!
1363  *
1364  * Note: it is legal to use SysCacheGetAttr() with a cacheId referencing
1365  * a different cache for the same catalog the tuple was fetched from.
1366  */
1367 Datum
1368 SysCacheGetAttr(int cacheId, HeapTuple tup,
1369  AttrNumber attributeNumber,
1370  bool *isNull)
1371 {
1372  /*
1373  * We just need to get the TupleDesc out of the cache entry, and then we
1374  * can apply heap_getattr(). Normally the cache control data is already
1375  * valid (because the caller recently fetched the tuple via this same
1376  * cache), but there are cases where we have to initialize the cache here.
1377  */
1378  if (cacheId < 0 || cacheId >= SysCacheSize ||
1379  !PointerIsValid(SysCache[cacheId]))
1380  elog(ERROR, "invalid cache ID: %d", cacheId);
1381  if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
1382  {
1383  InitCatCachePhase2(SysCache[cacheId], false);
1384  Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
1385  }
1386 
1387  return heap_getattr(tup, attributeNumber,
1388  SysCache[cacheId]->cc_tupdesc,
1389  isNull);
1390 }
1391 
1392 /*
1393  * GetSysCacheHashValue
1394  *
1395  * Get the hash value that would be used for a tuple in the specified cache
1396  * with the given search keys.
1397  *
1398  * The reason for exposing this as part of the API is that the hash value is
1399  * exposed in cache invalidation operations, so there are places outside the
1400  * catcache code that need to be able to compute the hash values.
1401  */
1402 uint32
1404  Datum key1,
1405  Datum key2,
1406  Datum key3,
1407  Datum key4)
1408 {
1409  if (cacheId < 0 || cacheId >= SysCacheSize ||
1410  !PointerIsValid(SysCache[cacheId]))
1411  elog(ERROR, "invalid cache ID: %d", cacheId);
1412 
1413  return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
1414 }
1415 
1416 /*
1417  * List-search interface
1418  */
1419 struct catclist *
1420 SearchSysCacheList(int cacheId, int nkeys,
1421  Datum key1, Datum key2, Datum key3)
1422 {
1423  if (cacheId < 0 || cacheId >= SysCacheSize ||
1424  !PointerIsValid(SysCache[cacheId]))
1425  elog(ERROR, "invalid cache ID: %d", cacheId);
1426 
1427  return SearchCatCacheList(SysCache[cacheId], nkeys,
1428  key1, key2, key3);
1429 }
1430 
1431 /*
1432  * SysCacheInvalidate
1433  *
1434  * Invalidate entries in the specified cache, given a hash value.
1435  * See CatCacheInvalidate() for more info.
1436  *
1437  * This routine is only quasi-public: it should only be used by inval.c.
1438  */
1439 void
1440 SysCacheInvalidate(int cacheId, uint32 hashValue)
1441 {
1442  if (cacheId < 0 || cacheId >= SysCacheSize)
1443  elog(ERROR, "invalid cache ID: %d", cacheId);
1444 
1445  /* if this cache isn't initialized yet, no need to do anything */
1446  if (!PointerIsValid(SysCache[cacheId]))
1447  return;
1448 
1449  CatCacheInvalidate(SysCache[cacheId], hashValue);
1450 }
1451 
1452 /*
1453  * Certain relations that do not have system caches send snapshot invalidation
1454  * messages in lieu of catcache messages. This is for the benefit of
1455  * GetCatalogSnapshot(), which can then reuse its existing MVCC snapshot
1456  * for scanning one of those catalogs, rather than taking a new one, if no
1457  * invalidation has been received.
1458  *
1459  * Relations that have syscaches need not (and must not) be listed here. The
1460  * catcache invalidation messages will also flush the snapshot. If you add a
1461  * syscache for one of these relations, remove it from this list.
1462  */
1463 bool
1465 {
1466  switch (relid)
1467  {
1468  case DbRoleSettingRelationId:
1469  case DependRelationId:
1470  case SharedDependRelationId:
1471  case DescriptionRelationId:
1472  case SharedDescriptionRelationId:
1473  case SecLabelRelationId:
1474  case SharedSecLabelRelationId:
1475  return true;
1476  default:
1477  break;
1478  }
1479 
1480  return false;
1481 }
1482 
1483 /*
1484  * Test whether a relation has a system cache.
1485  */
1486 bool
1488 {
1489  int low = 0,
1490  high = SysCacheRelationOidSize - 1;
1491 
1492  while (low <= high)
1493  {
1494  int middle = low + (high - low) / 2;
1495 
1496  if (SysCacheRelationOid[middle] == relid)
1497  return true;
1498  if (SysCacheRelationOid[middle] < relid)
1499  low = middle + 1;
1500  else
1501  high = middle - 1;
1502  }
1503 
1504  return false;
1505 }
1506 
1507 /*
1508  * Test whether a relation supports a system cache, ie it is either a
1509  * cached table or the index used for a cache.
1510  */
1511 bool
1513 {
1514  int low = 0,
1515  high = SysCacheSupportingRelOidSize - 1;
1516 
1517  while (low <= high)
1518  {
1519  int middle = low + (high - low) / 2;
1520 
1521  if (SysCacheSupportingRelOid[middle] == relid)
1522  return true;
1523  if (SysCacheSupportingRelOid[middle] < relid)
1524  low = middle + 1;
1525  else
1526  high = middle - 1;
1527  }
1528 
1529  return false;
1530 }
1531 
1532 
1533 /*
1534  * OID comparator for pg_qsort
1535  */
1536 static int
1537 oid_compare(const void *a, const void *b)
1538 {
1539  Oid oa = *((const Oid *) a);
1540  Oid ob = *((const Oid *) b);
1541 
1542  if (oa == ob)
1543  return 0;
1544  return (oa > ob) ? 1 : -1;
1545 }
HeapTuple SearchSysCache(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:1099
signed short int16
Definition: c.h:312
#define ConstraintOidIndexId
Definition: indexing.h:130
#define AttributeRelidNumIndexId
Definition: indexing.h:94
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:722
#define NamespaceOidIndexId
Definition: indexing.h:197
#define ProcedureOidIndexId
Definition: indexing.h:218
#define CollationOidIndexId
Definition: indexing.h:121
static bool CacheInitialized
Definition: syscache.c:976
HeapTuple SearchSysCacheAttNum(Oid relid, int16 attnum)
Definition: syscache.c:1311
bool RelationHasSysCache(Oid relid)
Definition: syscache.c:1487
#define GETSTRUCT(TUP)
Definition: htup_details.h:673
#define IndexRelidIndexId
Definition: indexing.h:166
static int SysCacheSupportingRelOidSize
Definition: syscache.c:984
void CatCacheInvalidate(CatCache *cache, uint32 hashValue)
Definition: catcache.c:568
#define ObjectIdAttributeNumber
Definition: sysattr.h:22
#define RewriteRelRulenameIndexId
Definition: indexing.h:225
static Oid SysCacheSupportingRelOid[SysCacheSize *2]
Definition: syscache.c:983
#define ForeignServerNameIndexId
Definition: indexing.h:296
#define PublicationNameIndexId
Definition: indexing.h:347
#define CastSourceTargetIndexId
Definition: indexing.h:109
#define Int16GetDatum(X)
Definition: postgres.h:434
#define ClassNameNspIndexId
Definition: indexing.h:114
static int SysCacheRelationOidSize
Definition: syscache.c:980
#define AuthIdOidIndexId
Definition: indexing.h:99
#define lengthof(array)
Definition: c.h:629
unsigned int Oid
Definition: postgres_ext.h:31
#define EnumTypIdLabelIndexId
Definition: indexing.h:159
Oid GetSysCacheOid(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:1221
bool SearchSysCacheExistsAttName(Oid relid, const char *attname)
Definition: syscache.c:1290
#define OpclassAmNameNspIndexId
Definition: indexing.h:200
#define AccessMethodOperatorIndexId
Definition: indexing.h:77
#define StatisticExtNameIndexId
Definition: indexing.h:190
#define AggregateFnoidIndexId
Definition: indexing.h:67
static const struct cachedesc cacheinfo[]
Definition: syscache.c:123
bool SearchSysCacheExists(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:1198
#define AmNameIndexId
Definition: indexing.h:70
#define SubscriptionRelSrrelidSrsubidIndexId
Definition: indexing.h:362
#define TSDictionaryOidIndexId
Definition: indexing.h:271
Oid reloid
Definition: syscache.c:116
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:795
#define ForeignDataWrapperNameIndexId
Definition: indexing.h:291
#define LanguageNameIndexId
Definition: indexing.h:177
#define SysCacheSize
Definition: syscache.h:112
#define ReplicationOriginIdentIndex
Definition: indexing.h:335
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define ERROR
Definition: elog.h:43
NameData attname
Definition: pg_attribute.h:40
#define PublicationObjectIndexId
Definition: indexing.h:344
#define SequenceRelidIndexId
Definition: indexing.h:228
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:1134
HeapTuple SearchSysCacheCopyAttName(Oid relid, const char *attname)
Definition: syscache.c:1271
#define TablespaceOidIndexId
Definition: indexing.h:239
#define PartitionedRelidIndexId
Definition: indexing.h:341
HeapTuple SearchSysCacheCopyAttNum(Oid relid, int16 attnum)
Definition: syscache.c:1334
#define ConversionDefaultIndexId
Definition: indexing.h:135
int nbuckets
Definition: syscache.c:120
#define CStringGetDatum(X)
Definition: postgres.h:561
HeapTuple SearchCatCache4(CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1206
struct catclist * SearchSysCacheList(int cacheId, int nkeys, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:1420
#define TransformOidIndexId
Definition: indexing.h:244
#define DatabaseOidIndexId
Definition: indexing.h:144
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
unsigned int uint32
Definition: c.h:325
#define OperatorNameNspIndexId
Definition: indexing.h:207
#define ClassOidIndexId
Definition: indexing.h:112
HeapTuple SearchSysCache4(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:1145
CatCache * InitCatCache(int id, Oid reloid, Oid indexoid, int nkeys, const int *key, int nbuckets)
Definition: catcache.c:779
Oid indoid
Definition: syscache.c:117
#define TSConfigOidIndexId
Definition: indexing.h:263
#define AuthMemRoleMemIndexId
Definition: indexing.h:102
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:786
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
#define PublicationRelPrrelidPrpubidIndexId
Definition: indexing.h:353
int nkeys
Definition: syscache.c:118
#define AccessMethodProcedureIndexId
Definition: indexing.h:82
static CatCache * SysCache[SysCacheSize]
Definition: syscache.c:974
#define OpfamilyAmNameNspIndexId
Definition: indexing.h:210
#define OperatorOidIndexId
Definition: indexing.h:205
uintptr_t Datum
Definition: postgres.h:365
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
static Oid SysCacheRelationOid[SysCacheSize]
Definition: syscache.c:979
#define EnumOidIndexId
Definition: indexing.h:157
#define AttributeRelidNameIndexId
Definition: indexing.h:92
#define TSDictionaryNameNspIndexId
Definition: indexing.h:269
#define TypeNameNspIndexId
Definition: indexing.h:286
#define OpclassOidIndexId
Definition: indexing.h:202
#define InvalidOid
Definition: postgres_ext.h:36
void ReleaseCatCache(HeapTuple tuple)
Definition: catcache.c:1458
int16 attnum
Definition: pg_attribute.h:79
uint32 GetSysCacheHashValue(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:1403
#define TSTemplateNameNspIndexId
Definition: indexing.h:279
#define ProcedureNameArgsNspIndexId
Definition: indexing.h:220
#define NamespaceNameIndexId
Definition: indexing.h:195
#define LanguageOidIndexId
Definition: indexing.h:179
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:699
bool RelationInvalidatesSnapshotsOnly(Oid relid)
Definition: syscache.c:1464
#define ForeignDataWrapperOidIndexId
Definition: indexing.h:289
#define StatisticRelidAttnumInhIndexId
Definition: indexing.h:236
void SysCacheInvalidate(int cacheId, uint32 hashValue)
Definition: syscache.c:1440
#define AuthMemMemRoleIndexId
Definition: indexing.h:104
#define EventTriggerOidIndexId
Definition: indexing.h:258
int key[4]
Definition: syscache.c:119
#define UserMappingOidIndexId
Definition: indexing.h:299
void pg_qsort(void *base, size_t nel, size_t elsize, int(*cmp)(const void *, const void *))
Definition: qsort.c:113
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1123
#define ConversionOidIndexId
Definition: indexing.h:139
#define UserMappingUserServerIndexId
Definition: indexing.h:301
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:1248
#define TSParserOidIndexId
Definition: indexing.h:276
#define CollationNameEncNspIndexId
Definition: indexing.h:119
#define RangeTypidIndexId
Definition: indexing.h:326
#define EventTriggerNameIndexId
Definition: indexing.h:256
#define DefaultAclRoleNspObjIndexId
Definition: indexing.h:307
#define PublicationRelObjectIndexId
Definition: indexing.h:350
HeapTuple SearchSysCacheCopy(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4)
Definition: syscache.c:1174
CatCList * SearchCatCacheList(CatCache *cache, int nkeys, Datum v1, Datum v2, Datum v3)
Definition: catcache.c:1524
HeapTuple SearchCatCache3(CatCache *cache, Datum v1, Datum v2, Datum v3)
Definition: catcache.c:1198
void InitCatalogCache(void)
Definition: syscache.c:998
HeapTuple SearchCatCache(CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1165
#define SubscriptionNameIndexId
Definition: indexing.h:359
static int oid_compare(const void *a, const void *b)
Definition: syscache.c:1537
int i
#define AccessMethodStrategyIndexId
Definition: indexing.h:75
#define TSConfigMapIndexId
Definition: indexing.h:266
#define ConversionNameNspIndexId
Definition: indexing.h:137
#define AmOidIndexId
Definition: indexing.h:72
#define StatisticExtOidIndexId
Definition: indexing.h:188
#define ReplicationOriginNameIndex
Definition: indexing.h:338
#define elog
Definition: elog.h:219
void InitCatCachePhase2(CatCache *cache, bool touch_index)
Definition: catcache.c:1050
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:712
bool RelationSupportsSysCache(Oid relid)
Definition: syscache.c:1512
uint32 GetCatCacheHashValue(CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4)
Definition: catcache.c:1490
#define TSTemplateOidIndexId
Definition: indexing.h:281
#define AuthIdRolnameIndexId
Definition: indexing.h:97
void InitCatalogCachePhase2(void)
Definition: syscache.c:1071
#define PointerIsValid(pointer)
Definition: c.h:593
#define ForeignTableRelidIndexId
Definition: indexing.h:304
HeapTuple SearchCatCache1(CatCache *cache, Datum v1)
Definition: catcache.c:1182
#define TSParserNameNspIndexId
Definition: indexing.h:274
int16 AttrNumber
Definition: attnum.h:21
HeapTuple SearchCatCache2(CatCache *cache, Datum v1, Datum v2)
Definition: catcache.c:1190
#define TSConfigNameNspIndexId
Definition: indexing.h:261
#define TransformTypeLangIndexId
Definition: indexing.h:246
#define TypeOidIndexId
Definition: indexing.h:284
#define ForeignServerOidIndexId
Definition: indexing.h:294
#define OpfamilyOidIndexId
Definition: indexing.h:212
#define SubscriptionObjectIndexId
Definition: indexing.h:356