1/*-------------------------------------------------------------------------
2 *
3 * syscache.c
4 * System cache management routines
5 *
6 * Portions Copyright (c) 1996-2019, 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"
30#include "catalog/pg_auth_members.h"
31#include "catalog/pg_authid.h"
32#include "catalog/pg_cast.h"
33#include "catalog/pg_collation.h"
34#include "catalog/pg_constraint.h"
35#include "catalog/pg_conversion.h"
36#include "catalog/pg_database.h"
37#include "catalog/pg_db_role_setting.h"
38#include "catalog/pg_default_acl.h"
39#include "catalog/pg_depend.h"
40#include "catalog/pg_description.h"
41#include "catalog/pg_enum.h"
42#include "catalog/pg_event_trigger.h"
43#include "catalog/pg_foreign_data_wrapper.h"
44#include "catalog/pg_foreign_server.h"
45#include "catalog/pg_foreign_table.h"
46#include "catalog/pg_language.h"
47#include "catalog/pg_namespace.h"
48#include "catalog/pg_opclass.h"
49#include "catalog/pg_operator.h"
50#include "catalog/pg_opfamily.h"
51#include "catalog/pg_partitioned_table.h"
52#include "catalog/pg_proc.h"
53#include "catalog/pg_publication.h"
54#include "catalog/pg_publication_rel.h"
55#include "catalog/pg_range.h"
56#include "catalog/pg_rewrite.h"
57#include "catalog/pg_seclabel.h"
58#include "catalog/pg_sequence.h"
59#include "catalog/pg_shdepend.h"
60#include "catalog/pg_shdescription.h"
61#include "catalog/pg_shseclabel.h"
62#include "catalog/pg_replication_origin.h"
63#include "catalog/pg_statistic.h"
64#include "catalog/pg_statistic_ext.h"
65#include "catalog/pg_statistic_ext_data.h"
66#include "catalog/pg_subscription.h"
67#include "catalog/pg_subscription_rel.h"
68#include "catalog/pg_tablespace.h"
69#include "catalog/pg_transform.h"
70#include "catalog/pg_ts_config.h"
71#include "catalog/pg_ts_config_map.h"
72#include "catalog/pg_ts_dict.h"
73#include "catalog/pg_ts_parser.h"
74#include "catalog/pg_ts_template.h"
75#include "catalog/pg_type.h"
76#include "catalog/pg_user_mapping.h"
77#include "utils/rel.h"
78#include "utils/catcache.h"
79#include "utils/syscache.h"
80
81
82/*---------------------------------------------------------------------------
83
84 Adding system caches:
85
86 Add your new cache to the list in include/utils/syscache.h.
87 Keep the list sorted alphabetically.
88
89 Add your entry to the cacheinfo[] array below. All cache lists are
90 alphabetical, so add it in the proper place. Specify the relation OID,
91 index OID, number of keys, key attribute numbers, and initial number of
92 hash buckets.
93
94 The number of hash buckets must be a power of 2. It's reasonable to
95 set this to the number of entries that might be in the particular cache
96 in a medium-size database.
97
98 There must be a unique index underlying each syscache (ie, an index
99 whose key is the same as that of the cache). If there is not one
100 already, add definitions for it to include/catalog/indexing.h: you need
101 to add a DECLARE_UNIQUE_INDEX macro and a #define for the index OID.
102 (Adding an index requires a catversion.h update, while simply
103 adding/deleting caches only requires a recompile.)
104
105 Finally, any place your relation gets heap_insert() or
106 heap_update() calls, use CatalogTupleInsert() or CatalogTupleUpdate()
107 instead, which also update indexes. The heap_* calls do not do that.
108
109*---------------------------------------------------------------------------
110*/
111
112/*
113 * struct cachedesc: information defining a single syscache
114 */
115struct cachedesc
116{
117 Oid reloid; /* OID of the relation being cached */
118 Oid indoid; /* OID of index relation for this cache */
119 int nkeys; /* # of keys needed for cache lookup */
120 int key[4]; /* attribute numbers of key attrs */
121 int nbuckets; /* number of hash buckets for this cache */
122};
123
124static const struct cachedesc cacheinfo[] = {
125 {AggregateRelationId, /* AGGFNOID */
126 AggregateFnoidIndexId,
127 1,
128 {
129 Anum_pg_aggregate_aggfnoid,
130 0,
131 0,
132 0
133 },
134 16
135 },
136 {AccessMethodRelationId, /* AMNAME */
137 AmNameIndexId,
138 1,
139 {
140 Anum_pg_am_amname,
141 0,
142 0,
143 0
144 },
145 4
146 },
147 {AccessMethodRelationId, /* AMOID */
148 AmOidIndexId,
149 1,
150 {
151 Anum_pg_am_oid,
152 0,
153 0,
154 0
155 },
156 4
157 },
158 {AccessMethodOperatorRelationId, /* AMOPOPID */
159 AccessMethodOperatorIndexId,
160 3,
161 {
162 Anum_pg_amop_amopopr,
163 Anum_pg_amop_amoppurpose,
164 Anum_pg_amop_amopfamily,
165 0
166 },
167 64
168 },
169 {AccessMethodOperatorRelationId, /* AMOPSTRATEGY */
170 AccessMethodStrategyIndexId,
171 4,
172 {
173 Anum_pg_amop_amopfamily,
174 Anum_pg_amop_amoplefttype,
175 Anum_pg_amop_amoprighttype,
176 Anum_pg_amop_amopstrategy
177 },
178 64
179 },
180 {AccessMethodProcedureRelationId, /* AMPROCNUM */
181 AccessMethodProcedureIndexId,
182 4,
183 {
184 Anum_pg_amproc_amprocfamily,
185 Anum_pg_amproc_amproclefttype,
186 Anum_pg_amproc_amprocrighttype,
187 Anum_pg_amproc_amprocnum
188 },
189 16
190 },
191 {AttributeRelationId, /* ATTNAME */
192 AttributeRelidNameIndexId,
193 2,
194 {
195 Anum_pg_attribute_attrelid,
196 Anum_pg_attribute_attname,
197 0,
198 0
199 },
200 32
201 },
202 {AttributeRelationId, /* ATTNUM */
203 AttributeRelidNumIndexId,
204 2,
205 {
206 Anum_pg_attribute_attrelid,
207 Anum_pg_attribute_attnum,
208 0,
209 0
210 },
211 128
212 },
213 {AuthMemRelationId, /* AUTHMEMMEMROLE */
214 AuthMemMemRoleIndexId,
215 2,
216 {
217 Anum_pg_auth_members_member,
218 Anum_pg_auth_members_roleid,
219 0,
220 0
221 },
222 8
223 },
224 {AuthMemRelationId, /* AUTHMEMROLEMEM */
225 AuthMemRoleMemIndexId,
226 2,
227 {
228 Anum_pg_auth_members_roleid,
229 Anum_pg_auth_members_member,
230 0,
231 0
232 },
233 8
234 },
235 {AuthIdRelationId, /* AUTHNAME */
236 AuthIdRolnameIndexId,
237 1,
238 {
239 Anum_pg_authid_rolname,
240 0,
241 0,
242 0
243 },
244 8
245 },
246 {AuthIdRelationId, /* AUTHOID */
247 AuthIdOidIndexId,
248 1,
249 {
250 Anum_pg_authid_oid,
251 0,
252 0,
253 0
254 },
255 8
256 },
257 {
258 CastRelationId, /* CASTSOURCETARGET */
259 CastSourceTargetIndexId,
260 2,
261 {
262 Anum_pg_cast_castsource,
263 Anum_pg_cast_casttarget,
264 0,
265 0
266 },
267 256
268 },
269 {OperatorClassRelationId, /* CLAAMNAMENSP */
270 OpclassAmNameNspIndexId,
271 3,
272 {
273 Anum_pg_opclass_opcmethod,
274 Anum_pg_opclass_opcname,
275 Anum_pg_opclass_opcnamespace,
276 0
277 },
278 8
279 },
280 {OperatorClassRelationId, /* CLAOID */
281 OpclassOidIndexId,
282 1,
283 {
284 Anum_pg_opclass_oid,
285 0,
286 0,
287 0
288 },
289 8
290 },
291 {CollationRelationId, /* COLLNAMEENCNSP */
292 CollationNameEncNspIndexId,
293 3,
294 {
295 Anum_pg_collation_collname,
296 Anum_pg_collation_collencoding,
297 Anum_pg_collation_collnamespace,
298 0
299 },
300 8
301 },
302 {CollationRelationId, /* COLLOID */
303 CollationOidIndexId,
304 1,
305 {
306 Anum_pg_collation_oid,
307 0,
308 0,
309 0
310 },
311 8
312 },
313 {ConversionRelationId, /* CONDEFAULT */
314 ConversionDefaultIndexId,
315 4,
316 {
317 Anum_pg_conversion_connamespace,
318 Anum_pg_conversion_conforencoding,
319 Anum_pg_conversion_contoencoding,
320 Anum_pg_conversion_oid
321 },
322 8
323 },
324 {ConversionRelationId, /* CONNAMENSP */
325 ConversionNameNspIndexId,
326 2,
327 {
328 Anum_pg_conversion_conname,
329 Anum_pg_conversion_connamespace,
330 0,
331 0
332 },
333 8
334 },
335 {ConstraintRelationId, /* CONSTROID */
336 ConstraintOidIndexId,
337 1,
338 {
339 Anum_pg_constraint_oid,
340 0,
341 0,
342 0
343 },
344 16
345 },
346 {ConversionRelationId, /* CONVOID */
347 ConversionOidIndexId,
348 1,
349 {
350 Anum_pg_conversion_oid,
351 0,
352 0,
353 0
354 },
355 8
356 },
357 {DatabaseRelationId, /* DATABASEOID */
358 DatabaseOidIndexId,
359 1,
360 {
361 Anum_pg_database_oid,
362 0,
363 0,
364 0
365 },
366 4
367 },
368 {DefaultAclRelationId, /* DEFACLROLENSPOBJ */
369 DefaultAclRoleNspObjIndexId,
370 3,
371 {
372 Anum_pg_default_acl_defaclrole,
373 Anum_pg_default_acl_defaclnamespace,
374 Anum_pg_default_acl_defaclobjtype,
375 0
376 },
377 8
378 },
379 {EnumRelationId, /* ENUMOID */
380 EnumOidIndexId,
381 1,
382 {
383 Anum_pg_enum_oid,
384 0,
385 0,
386 0
387 },
388 8
389 },
390 {EnumRelationId, /* ENUMTYPOIDNAME */
391 EnumTypIdLabelIndexId,
392 2,
393 {
394 Anum_pg_enum_enumtypid,
395 Anum_pg_enum_enumlabel,
396 0,
397 0
398 },
399 8
400 },
401 {EventTriggerRelationId, /* EVENTTRIGGERNAME */
402 EventTriggerNameIndexId,
403 1,
404 {
405 Anum_pg_event_trigger_evtname,
406 0,
407 0,
408 0
409 },
410 8
411 },
412 {EventTriggerRelationId, /* EVENTTRIGGEROID */
413 EventTriggerOidIndexId,
414 1,
415 {
416 Anum_pg_event_trigger_oid,
417 0,
418 0,
419 0
420 },
421 8
422 },
423 {ForeignDataWrapperRelationId, /* FOREIGNDATAWRAPPERNAME */
424 ForeignDataWrapperNameIndexId,
425 1,
426 {
427 Anum_pg_foreign_data_wrapper_fdwname,
428 0,
429 0,
430 0
431 },
432 2
433 },
434 {ForeignDataWrapperRelationId, /* FOREIGNDATAWRAPPEROID */
435 ForeignDataWrapperOidIndexId,
436 1,
437 {
438 Anum_pg_foreign_data_wrapper_oid,
439 0,
440 0,
441 0
442 },
443 2
444 },
445 {ForeignServerRelationId, /* FOREIGNSERVERNAME */
446 ForeignServerNameIndexId,
447 1,
448 {
449 Anum_pg_foreign_server_srvname,
450 0,
451 0,
452 0
453 },
454 2
455 },
456 {ForeignServerRelationId, /* FOREIGNSERVEROID */
457 ForeignServerOidIndexId,
458 1,
459 {
460 Anum_pg_foreign_server_oid,
461 0,
462 0,
463 0
464 },
465 2
466 },
467 {ForeignTableRelationId, /* FOREIGNTABLEREL */
468 ForeignTableRelidIndexId,
469 1,
470 {
471 Anum_pg_foreign_table_ftrelid,
472 0,
473 0,
474 0
475 },
476 4
477 },
478 {IndexRelationId, /* INDEXRELID */
479 IndexRelidIndexId,
480 1,
481 {
482 Anum_pg_index_indexrelid,
483 0,
484 0,
485 0
486 },
487 64
488 },
489 {LanguageRelationId, /* LANGNAME */
490 LanguageNameIndexId,
491 1,
492 {
493 Anum_pg_language_lanname,
494 0,
495 0,
496 0
497 },
498 4
499 },
500 {LanguageRelationId, /* LANGOID */
501 LanguageOidIndexId,
502 1,
503 {
504 Anum_pg_language_oid,
505 0,
506 0,
507 0
508 },
509 4
510 },
511 {NamespaceRelationId, /* NAMESPACENAME */
512 NamespaceNameIndexId,
513 1,
514 {
515 Anum_pg_namespace_nspname,
516 0,
517 0,
518 0
519 },
520 4
521 },
522 {NamespaceRelationId, /* NAMESPACEOID */
523 NamespaceOidIndexId,
524 1,
525 {
526 Anum_pg_namespace_oid,
527 0,
528 0,
529 0
530 },
531 16
532 },
533 {OperatorRelationId, /* OPERNAMENSP */
534 OperatorNameNspIndexId,
535 4,
536 {
537 Anum_pg_operator_oprname,
538 Anum_pg_operator_oprleft,
539 Anum_pg_operator_oprright,
540 Anum_pg_operator_oprnamespace
541 },
542 256
543 },
544 {OperatorRelationId, /* OPEROID */
545 OperatorOidIndexId,
546 1,
547 {
548 Anum_pg_operator_oid,
549 0,
550 0,
551 0
552 },
553 32
554 },
555 {OperatorFamilyRelationId, /* OPFAMILYAMNAMENSP */
556 OpfamilyAmNameNspIndexId,
557 3,
558 {
559 Anum_pg_opfamily_opfmethod,
560 Anum_pg_opfamily_opfname,
561 Anum_pg_opfamily_opfnamespace,
562 0
563 },
564 8
565 },
566 {OperatorFamilyRelationId, /* OPFAMILYOID */
567 OpfamilyOidIndexId,
568 1,
569 {
570 Anum_pg_opfamily_oid,
571 0,
572 0,
573 0
574 },
575 8
576 },
577 {PartitionedRelationId, /* PARTRELID */
578 PartitionedRelidIndexId,
579 1,
580 {
581 Anum_pg_partitioned_table_partrelid,
582 0,
583 0,
584 0
585 },
586 32
587 },
588 {ProcedureRelationId, /* PROCNAMEARGSNSP */
589 ProcedureNameArgsNspIndexId,
590 3,
591 {
592 Anum_pg_proc_proname,
593 Anum_pg_proc_proargtypes,
594 Anum_pg_proc_pronamespace,
595 0
596 },
597 128
598 },
599 {ProcedureRelationId, /* PROCOID */
600 ProcedureOidIndexId,
601 1,
602 {
603 Anum_pg_proc_oid,
604 0,
605 0,
606 0
607 },
608 128
609 },
610 {PublicationRelationId, /* PUBLICATIONNAME */
611 PublicationNameIndexId,
612 1,
613 {
614 Anum_pg_publication_pubname,
615 0,
616 0,
617 0
618 },
619 8
620 },
621 {PublicationRelationId, /* PUBLICATIONOID */
622 PublicationObjectIndexId,
623 1,
624 {
625 Anum_pg_publication_oid,
626 0,
627 0,
628 0
629 },
630 8
631 },
632 {PublicationRelRelationId, /* PUBLICATIONREL */
633 PublicationRelObjectIndexId,
634 1,
635 {
636 Anum_pg_publication_rel_oid,
637 0,
638 0,
639 0
640 },
641 64
642 },
643 {PublicationRelRelationId, /* PUBLICATIONRELMAP */
644 PublicationRelPrrelidPrpubidIndexId,
645 2,
646 {
647 Anum_pg_publication_rel_prrelid,
648 Anum_pg_publication_rel_prpubid,
649 0,
650 0
651 },
652 64
653 },
654 {RangeRelationId, /* RANGETYPE */
655 RangeTypidIndexId,
656 1,
657 {
658 Anum_pg_range_rngtypid,
659 0,
660 0,
661 0
662 },
663 4
664 },
665 {RelationRelationId, /* RELNAMENSP */
666 ClassNameNspIndexId,
667 2,
668 {
669 Anum_pg_class_relname,
670 Anum_pg_class_relnamespace,
671 0,
672 0
673 },
674 128
675 },
676 {RelationRelationId, /* RELOID */
677 ClassOidIndexId,
678 1,
679 {
680 Anum_pg_class_oid,
681 0,
682 0,
683 0
684 },
685 128
686 },
687 {ReplicationOriginRelationId, /* REPLORIGIDENT */
688 ReplicationOriginIdentIndex,
689 1,
690 {
691 Anum_pg_replication_origin_roident,
692 0,
693 0,
694 0
695 },
696 16
697 },
698 {ReplicationOriginRelationId, /* REPLORIGNAME */
699 ReplicationOriginNameIndex,
700 1,
701 {
702 Anum_pg_replication_origin_roname,
703 0,
704 0,
705 0
706 },
707 16
708 },
709 {RewriteRelationId, /* RULERELNAME */
710 RewriteRelRulenameIndexId,
711 2,
712 {
713 Anum_pg_rewrite_ev_class,
714 Anum_pg_rewrite_rulename,
715 0,
716 0
717 },
718 8
719 },
720 {SequenceRelationId, /* SEQRELID */
721 SequenceRelidIndexId,
722 1,
723 {
724 Anum_pg_sequence_seqrelid,
725 0,
726 0,
727 0
728 },
729 32
730 },
731 {StatisticExtDataRelationId, /* STATEXTDATASTXOID */
732 StatisticExtDataStxoidIndexId,
733 1,
734 {
735 Anum_pg_statistic_ext_data_stxoid,
736 0,
737 0,
738 0
739 },
740 4
741 },
742 {StatisticExtRelationId, /* STATEXTNAMENSP */
743 StatisticExtNameIndexId,
744 2,
745 {
746 Anum_pg_statistic_ext_stxname,
747 Anum_pg_statistic_ext_stxnamespace,
748 0,
749 0
750 },
751 4
752 },
753 {StatisticExtRelationId, /* STATEXTOID */
754 StatisticExtOidIndexId,
755 1,
756 {
757 Anum_pg_statistic_ext_oid,
758 0,
759 0,
760 0
761 },
762 4
763 },
764 {StatisticRelationId, /* STATRELATTINH */
765 StatisticRelidAttnumInhIndexId,
766 3,
767 {
768 Anum_pg_statistic_starelid,
769 Anum_pg_statistic_staattnum,
770 Anum_pg_statistic_stainherit,
771 0
772 },
773 128
774 },
775 {SubscriptionRelationId, /* SUBSCRIPTIONNAME */
776 SubscriptionNameIndexId,
777 2,
778 {
779 Anum_pg_subscription_subdbid,
780 Anum_pg_subscription_subname,
781 0,
782 0
783 },
784 4
785 },
786 {SubscriptionRelationId, /* SUBSCRIPTIONOID */
787 SubscriptionObjectIndexId,
788 1,
789 {
790 Anum_pg_subscription_oid,
791 0,
792 0,
793 0
794 },
795 4
796 },
797 {SubscriptionRelRelationId, /* SUBSCRIPTIONRELMAP */
798 SubscriptionRelSrrelidSrsubidIndexId,
799 2,
800 {
801 Anum_pg_subscription_rel_srrelid,
802 Anum_pg_subscription_rel_srsubid,
803 0,
804 0
805 },
806 64
807 },
808 {TableSpaceRelationId, /* TABLESPACEOID */
809 TablespaceOidIndexId,
810 1,
811 {
812 Anum_pg_tablespace_oid,
813 0,
814 0,
815 0,
816 },
817 4
818 },
819 {TransformRelationId, /* TRFOID */
820 TransformOidIndexId,
821 1,
822 {
823 Anum_pg_transform_oid,
824 0,
825 0,
826 0,
827 },
828 16
829 },
830 {TransformRelationId, /* TRFTYPELANG */
831 TransformTypeLangIndexId,
832 2,
833 {
834 Anum_pg_transform_trftype,
835 Anum_pg_transform_trflang,
836 0,
837 0,
838 },
839 16
840 },
841 {TSConfigMapRelationId, /* TSCONFIGMAP */
842 TSConfigMapIndexId,
843 3,
844 {
845 Anum_pg_ts_config_map_mapcfg,
846 Anum_pg_ts_config_map_maptokentype,
847 Anum_pg_ts_config_map_mapseqno,
848 0
849 },
850 2
851 },
852 {TSConfigRelationId, /* TSCONFIGNAMENSP */
853 TSConfigNameNspIndexId,
854 2,
855 {
856 Anum_pg_ts_config_cfgname,
857 Anum_pg_ts_config_cfgnamespace,
858 0,
859 0
860 },
861 2
862 },
863 {TSConfigRelationId, /* TSCONFIGOID */
864 TSConfigOidIndexId,
865 1,
866 {
867 Anum_pg_ts_config_oid,
868 0,
869 0,
870 0
871 },
872 2
873 },
874 {TSDictionaryRelationId, /* TSDICTNAMENSP */
875 TSDictionaryNameNspIndexId,
876 2,
877 {
878 Anum_pg_ts_dict_dictname,
879 Anum_pg_ts_dict_dictnamespace,
880 0,
881 0
882 },
883 2
884 },
885 {TSDictionaryRelationId, /* TSDICTOID */
886 TSDictionaryOidIndexId,
887 1,
888 {
889 Anum_pg_ts_dict_oid,
890 0,
891 0,
892 0
893 },
894 2
895 },
896 {TSParserRelationId, /* TSPARSERNAMENSP */
897 TSParserNameNspIndexId,
898 2,
899 {
900 Anum_pg_ts_parser_prsname,
901 Anum_pg_ts_parser_prsnamespace,
902 0,
903 0
904 },
905 2
906 },
907 {TSParserRelationId, /* TSPARSEROID */
908 TSParserOidIndexId,
909 1,
910 {
911 Anum_pg_ts_parser_oid,
912 0,
913 0,
914 0
915 },
916 2
917 },
918 {TSTemplateRelationId, /* TSTEMPLATENAMENSP */
919 TSTemplateNameNspIndexId,
920 2,
921 {
922 Anum_pg_ts_template_tmplname,
923 Anum_pg_ts_template_tmplnamespace,
924 0,
925 0
926 },
927 2
928 },
929 {TSTemplateRelationId, /* TSTEMPLATEOID */
930 TSTemplateOidIndexId,
931 1,
932 {
933 Anum_pg_ts_template_oid,
934 0,
935 0,
936 0
937 },
938 2
939 },
940 {TypeRelationId, /* TYPENAMENSP */
941 TypeNameNspIndexId,
942 2,
943 {
944 Anum_pg_type_typname,
945 Anum_pg_type_typnamespace,
946 0,
947 0
948 },
949 64
950 },
951 {TypeRelationId, /* TYPEOID */
952 TypeOidIndexId,
953 1,
954 {
955 Anum_pg_type_oid,
956 0,
957 0,
958 0
959 },
960 64
961 },
962 {UserMappingRelationId, /* USERMAPPINGOID */
963 UserMappingOidIndexId,
964 1,
965 {
966 Anum_pg_user_mapping_oid,
967 0,
968 0,
969 0
970 },
971 2
972 },
973 {UserMappingRelationId, /* USERMAPPINGUSERSERVER */
974 UserMappingUserServerIndexId,
975 2,
976 {
977 Anum_pg_user_mapping_umuser,
978 Anum_pg_user_mapping_umserver,
979 0,
980 0
981 },
982 2
983 }
984};
985
986static CatCache *SysCache[SysCacheSize];
987
988static bool CacheInitialized = false;
989
990/* Sorted array of OIDs of tables that have caches on them */
991static Oid SysCacheRelationOid[SysCacheSize];
992static int SysCacheRelationOidSize;
993
994/* Sorted array of OIDs of tables and indexes used by caches */
995static Oid SysCacheSupportingRelOid[SysCacheSize * 2];
996static int SysCacheSupportingRelOidSize;
997
998static int oid_compare(const void *a, const void *b);
999
1000
1001/*
1002 * InitCatalogCache - initialize the caches
1003 *
1004 * Note that no database access is done here; we only allocate memory
1005 * and initialize the cache structure. Interrogation of the database
1006 * to complete initialization of a cache happens upon first use
1007 * of that cache.
1008 */
1009void
1010InitCatalogCache(void)
1011{
1012 int cacheId;
1013 int i,
1014 j;
1015
1016 StaticAssertStmt(SysCacheSize == (int) lengthof(cacheinfo),
1017 "SysCacheSize does not match syscache.c's array");
1018
1019 Assert(!CacheInitialized);
1020
1021 SysCacheRelationOidSize = SysCacheSupportingRelOidSize = 0;
1022
1023 for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
1024 {
1025 SysCache[cacheId] = InitCatCache(cacheId,
1026 cacheinfo[cacheId].reloid,
1027 cacheinfo[cacheId].indoid,
1028 cacheinfo[cacheId].nkeys,
1029 cacheinfo[cacheId].key,
1030 cacheinfo[cacheId].nbuckets);
1031 if (!PointerIsValid(SysCache[cacheId]))
1032 elog(ERROR, "could not initialize cache %u (%d)",
1033 cacheinfo[cacheId].reloid, cacheId);
1034 /* Accumulate data for OID lists, too */
1035 SysCacheRelationOid[SysCacheRelationOidSize++] =
1036 cacheinfo[cacheId].reloid;
1037 SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
1038 cacheinfo[cacheId].reloid;
1039 SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
1040 cacheinfo[cacheId].indoid;
1041 /* see comments for RelationInvalidatesSnapshotsOnly */
1042 Assert(!RelationInvalidatesSnapshotsOnly(cacheinfo[cacheId].reloid));
1043 }
1044
1045 Assert(SysCacheRelationOidSize <= lengthof(SysCacheRelationOid));
1046 Assert(SysCacheSupportingRelOidSize <= lengthof(SysCacheSupportingRelOid));
1047
1048 /* Sort and de-dup OID arrays, so we can use binary search. */
1049 pg_qsort(SysCacheRelationOid, SysCacheRelationOidSize,
1050 sizeof(Oid), oid_compare);
1051 for (i = 1, j = 0; i < SysCacheRelationOidSize; i++)
1052 {
1053 if (SysCacheRelationOid[i] != SysCacheRelationOid[j])
1054 SysCacheRelationOid[++j] = SysCacheRelationOid[i];
1055 }
1056 SysCacheRelationOidSize = j + 1;
1057
1058 pg_qsort(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
1059 sizeof(Oid), oid_compare);
1060 for (i = 1, j = 0; i < SysCacheSupportingRelOidSize; i++)
1061 {
1062 if (SysCacheSupportingRelOid[i] != SysCacheSupportingRelOid[j])
1063 SysCacheSupportingRelOid[++j] = SysCacheSupportingRelOid[i];
1064 }
1065 SysCacheSupportingRelOidSize = j + 1;
1066
1067 CacheInitialized = true;
1068}
1069
1070/*
1071 * InitCatalogCachePhase2 - finish initializing the caches
1072 *
1073 * Finish initializing all the caches, including necessary database
1074 * access.
1075 *
1076 * This is *not* essential; normally we allow syscaches to be initialized
1077 * on first use. However, it is useful as a mechanism to preload the
1078 * relcache with entries for the most-commonly-used system catalogs.
1079 * Therefore, we invoke this routine when we need to write a new relcache
1080 * init file.
1081 */
1082void
1083InitCatalogCachePhase2(void)
1084{
1085 int cacheId;
1086
1087 Assert(CacheInitialized);
1088
1089 for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
1090 InitCatCachePhase2(SysCache[cacheId], true);
1091}
1092
1093
1094/*
1095 * SearchSysCache
1096 *
1097 * A layer on top of SearchCatCache that does the initialization and
1098 * key-setting for you.
1099 *
1100 * Returns the cache copy of the tuple if one is found, NULL if not.
1101 * The tuple is the 'cache' copy and must NOT be modified!
1102 *
1103 * When the caller is done using the tuple, call ReleaseSysCache()
1104 * to release the reference count grabbed by SearchSysCache(). If this
1105 * is not done, the tuple will remain locked in cache until end of
1106 * transaction, which is tolerable but not desirable.
1107 *
1108 * CAUTION: The tuple that is returned must NOT be freed by the caller!
1109 */
1110HeapTuple
1111SearchSysCache(int cacheId,
1112 Datum key1,
1113 Datum key2,
1114 Datum key3,
1115 Datum key4)
1116{
1117 Assert(cacheId >= 0 && cacheId < SysCacheSize &&
1118 PointerIsValid(SysCache[cacheId]));
1119
1120 return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
1121}
1122
1123HeapTuple
1124SearchSysCache1(int cacheId,
1125 Datum key1)
1126{
1127 Assert(cacheId >= 0 && cacheId < SysCacheSize &&
1128 PointerIsValid(SysCache[cacheId]));
1129 Assert(SysCache[cacheId]->cc_nkeys == 1);
1130
1131 return SearchCatCache1(SysCache[cacheId], key1);
1132}
1133
1134HeapTuple
1135SearchSysCache2(int cacheId,
1136 Datum key1, Datum key2)
1137{
1138 Assert(cacheId >= 0 && cacheId < SysCacheSize &&
1139 PointerIsValid(SysCache[cacheId]));
1140 Assert(SysCache[cacheId]->cc_nkeys == 2);
1141
1142 return SearchCatCache2(SysCache[cacheId], key1, key2);
1143}
1144
1145HeapTuple
1146SearchSysCache3(int cacheId,
1147 Datum key1, Datum key2, Datum key3)
1148{
1149 Assert(cacheId >= 0 && cacheId < SysCacheSize &&
1150 PointerIsValid(SysCache[cacheId]));
1151 Assert(SysCache[cacheId]->cc_nkeys == 3);
1152
1153 return SearchCatCache3(SysCache[cacheId], key1, key2, key3);
1154}
1155
1156HeapTuple
1157SearchSysCache4(int cacheId,
1158 Datum key1, Datum key2, Datum key3, Datum key4)
1159{
1160 Assert(cacheId >= 0 && cacheId < SysCacheSize &&
1161 PointerIsValid(SysCache[cacheId]));
1162 Assert(SysCache[cacheId]->cc_nkeys == 4);
1163
1164 return SearchCatCache4(SysCache[cacheId], key1, key2, key3, key4);
1165}
1166
1167/*
1168 * ReleaseSysCache
1169 * Release previously grabbed reference count on a tuple
1170 */
1171void
1172ReleaseSysCache(HeapTuple tuple)
1173{
1174 ReleaseCatCache(tuple);
1175}
1176
1177/*
1178 * SearchSysCacheCopy
1179 *
1180 * A convenience routine that does SearchSysCache and (if successful)
1181 * returns a modifiable copy of the syscache entry. The original
1182 * syscache entry is released before returning. The caller should
1183 * heap_freetuple() the result when done with it.
1184 */
1185HeapTuple
1186SearchSysCacheCopy(int cacheId,
1187 Datum key1,
1188 Datum key2,
1189 Datum key3,
1190 Datum key4)
1191{
1192 HeapTuple tuple,
1193 newtuple;
1194
1195 tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1196 if (!HeapTupleIsValid(tuple))
1197 return tuple;
1198 newtuple = heap_copytuple(tuple);
1199 ReleaseSysCache(tuple);
1200 return newtuple;
1201}
1202
1203/*
1204 * SearchSysCacheExists
1205 *
1206 * A convenience routine that just probes to see if a tuple can be found.
1207 * No lock is retained on the syscache entry.
1208 */
1209bool
1210SearchSysCacheExists(int cacheId,
1211 Datum key1,
1212 Datum key2,
1213 Datum key3,
1214 Datum key4)
1215{
1216 HeapTuple tuple;
1217
1218 tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1219 if (!HeapTupleIsValid(tuple))
1220 return false;
1221 ReleaseSysCache(tuple);
1222 return true;
1223}
1224
1225/*
1226 * GetSysCacheOid
1227 *
1228 * A convenience routine that does SearchSysCache and returns the OID in the
1229 * oidcol column of the found tuple, or InvalidOid if no tuple could be found.
1230 * No lock is retained on the syscache entry.
1231 */
1232Oid
1233GetSysCacheOid(int cacheId,
1234 AttrNumber oidcol,
1235 Datum key1,
1236 Datum key2,
1237 Datum key3,
1238 Datum key4)
1239{
1240 HeapTuple tuple;
1241 bool isNull;
1242 Oid result;
1243
1244 tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1245 if (!HeapTupleIsValid(tuple))
1246 return InvalidOid;
1247 result = heap_getattr(tuple, oidcol,
1248 SysCache[cacheId]->cc_tupdesc,
1249 &isNull);
1250 Assert(!isNull); /* columns used as oids should never be NULL */
1251 ReleaseSysCache(tuple);
1252 return result;
1253}
1254
1255
1256/*
1257 * SearchSysCacheAttName
1258 *
1259 * This routine is equivalent to SearchSysCache on the ATTNAME cache,
1260 * except that it will return NULL if the found attribute is marked
1261 * attisdropped. This is convenient for callers that want to act as
1262 * though dropped attributes don't exist.
1263 */
1264HeapTuple
1265SearchSysCacheAttName(Oid relid, const char *attname)
1266{
1267 HeapTuple tuple;
1268
1269 tuple = SearchSysCache2(ATTNAME,
1270 ObjectIdGetDatum(relid),
1271 CStringGetDatum(attname));
1272 if (!HeapTupleIsValid(tuple))
1273 return NULL;
1274 if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
1275 {
1276 ReleaseSysCache(tuple);
1277 return NULL;
1278 }
1279 return tuple;
1280}
1281
1282/*
1283 * SearchSysCacheCopyAttName
1284 *
1285 * As above, an attisdropped-aware version of SearchSysCacheCopy.
1286 */
1287HeapTuple
1288SearchSysCacheCopyAttName(Oid relid, const char *attname)
1289{
1290 HeapTuple tuple,
1291 newtuple;
1292
1293 tuple = SearchSysCacheAttName(relid, attname);
1294 if (!HeapTupleIsValid(tuple))
1295 return tuple;
1296 newtuple = heap_copytuple(tuple);
1297 ReleaseSysCache(tuple);
1298 return newtuple;
1299}
1300
1301/*
1302 * SearchSysCacheExistsAttName
1303 *
1304 * As above, an attisdropped-aware version of SearchSysCacheExists.
1305 */
1306bool
1307SearchSysCacheExistsAttName(Oid relid, const char *attname)
1308{
1309 HeapTuple tuple;
1310
1311 tuple = SearchSysCacheAttName(relid, attname);
1312 if (!HeapTupleIsValid(tuple))
1313 return false;
1314 ReleaseSysCache(tuple);
1315 return true;
1316}
1317
1318
1319/*
1320 * SearchSysCacheAttNum
1321 *
1322 * This routine is equivalent to SearchSysCache on the ATTNUM cache,
1323 * except that it will return NULL if the found attribute is marked
1324 * attisdropped. This is convenient for callers that want to act as
1325 * though dropped attributes don't exist.
1326 */
1327HeapTuple
1328SearchSysCacheAttNum(Oid relid, int16 attnum)
1329{
1330 HeapTuple tuple;
1331
1332 tuple = SearchSysCache2(ATTNUM,
1333 ObjectIdGetDatum(relid),
1334 Int16GetDatum(attnum));
1335 if (!HeapTupleIsValid(tuple))
1336 return NULL;
1337 if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
1338 {
1339 ReleaseSysCache(tuple);
1340 return NULL;
1341 }
1342 return tuple;
1343}
1344
1345/*
1346 * SearchSysCacheCopyAttNum
1347 *
1348 * As above, an attisdropped-aware version of SearchSysCacheCopy.
1349 */
1350HeapTuple
1351SearchSysCacheCopyAttNum(Oid relid, int16 attnum)
1352{
1353 HeapTuple tuple,
1354 newtuple;
1355
1356 tuple = SearchSysCacheAttNum(relid, attnum);
1357 if (!HeapTupleIsValid(tuple))
1358 return NULL;
1359 newtuple = heap_copytuple(tuple);
1360 ReleaseSysCache(tuple);
1361 return newtuple;
1362}
1363
1364
1365/*
1366 * SysCacheGetAttr
1367 *
1368 * Given a tuple previously fetched by SearchSysCache(),
1369 * extract a specific attribute.
1370 *
1371 * This is equivalent to using heap_getattr() on a tuple fetched
1372 * from a non-cached relation. Usually, this is only used for attributes
1373 * that could be NULL or variable length; the fixed-size attributes in
1374 * a system table are accessed just by mapping the tuple onto the C struct
1375 * declarations from include/catalog/.
1376 *
1377 * As with heap_getattr(), if the attribute is of a pass-by-reference type
1378 * then a pointer into the tuple data area is returned --- the caller must
1379 * not modify or pfree the datum!
1380 *
1381 * Note: it is legal to use SysCacheGetAttr() with a cacheId referencing
1382 * a different cache for the same catalog the tuple was fetched from.
1383 */
1384Datum
1385SysCacheGetAttr(int cacheId, HeapTuple tup,
1386 AttrNumber attributeNumber,
1387 bool *isNull)
1388{
1389 /*
1390 * We just need to get the TupleDesc out of the cache entry, and then we
1391 * can apply heap_getattr(). Normally the cache control data is already
1392 * valid (because the caller recently fetched the tuple via this same
1393 * cache), but there are cases where we have to initialize the cache here.
1394 */
1395 if (cacheId < 0 || cacheId >= SysCacheSize ||
1396 !PointerIsValid(SysCache[cacheId]))
1397 elog(ERROR, "invalid cache ID: %d", cacheId);
1398 if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
1399 {
1400 InitCatCachePhase2(SysCache[cacheId], false);
1401 Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
1402 }
1403
1404 return heap_getattr(tup, attributeNumber,
1405 SysCache[cacheId]->cc_tupdesc,
1406 isNull);
1407}
1408
1409/*
1410 * GetSysCacheHashValue
1411 *
1412 * Get the hash value that would be used for a tuple in the specified cache
1413 * with the given search keys.
1414 *
1415 * The reason for exposing this as part of the API is that the hash value is
1416 * exposed in cache invalidation operations, so there are places outside the
1417 * catcache code that need to be able to compute the hash values.
1418 */
1419uint32
1420GetSysCacheHashValue(int cacheId,
1421 Datum key1,
1422 Datum key2,
1423 Datum key3,
1424 Datum key4)
1425{
1426 if (cacheId < 0 || cacheId >= SysCacheSize ||
1427 !PointerIsValid(SysCache[cacheId]))
1428 elog(ERROR, "invalid cache ID: %d", cacheId);
1429
1430 return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
1431}
1432
1433/*
1434 * List-search interface
1435 */
1436struct catclist *
1437SearchSysCacheList(int cacheId, int nkeys,
1438 Datum key1, Datum key2, Datum key3)
1439{
1440 if (cacheId < 0 || cacheId >= SysCacheSize ||
1441 !PointerIsValid(SysCache[cacheId]))
1442 elog(ERROR, "invalid cache ID: %d", cacheId);
1443
1444 return SearchCatCacheList(SysCache[cacheId], nkeys,
1445 key1, key2, key3);
1446}
1447
1448/*
1449 * SysCacheInvalidate
1450 *
1451 * Invalidate entries in the specified cache, given a hash value.
1452 * See CatCacheInvalidate() for more info.
1453 *
1454 * This routine is only quasi-public: it should only be used by inval.c.
1455 */
1456void
1457SysCacheInvalidate(int cacheId, uint32 hashValue)
1458{
1459 if (cacheId < 0 || cacheId >= SysCacheSize)
1460 elog(ERROR, "invalid cache ID: %d", cacheId);
1461
1462 /* if this cache isn't initialized yet, no need to do anything */
1463 if (!PointerIsValid(SysCache[cacheId]))
1464 return;
1465
1466 CatCacheInvalidate(SysCache[cacheId], hashValue);
1467}
1468
1469/*
1470 * Certain relations that do not have system caches send snapshot invalidation
1471 * messages in lieu of catcache messages. This is for the benefit of
1472 * GetCatalogSnapshot(), which can then reuse its existing MVCC snapshot
1473 * for scanning one of those catalogs, rather than taking a new one, if no
1474 * invalidation has been received.
1475 *
1476 * Relations that have syscaches need not (and must not) be listed here. The
1477 * catcache invalidation messages will also flush the snapshot. If you add a
1478 * syscache for one of these relations, remove it from this list.
1479 */
1480bool
1481RelationInvalidatesSnapshotsOnly(Oid relid)
1482{
1483 switch (relid)
1484 {
1485 case DbRoleSettingRelationId:
1486 case DependRelationId:
1487 case SharedDependRelationId:
1488 case DescriptionRelationId:
1489 case SharedDescriptionRelationId:
1490 case SecLabelRelationId:
1491 case SharedSecLabelRelationId:
1492 return true;
1493 default:
1494 break;
1495 }
1496
1497 return false;
1498}
1499
1500/*
1501 * Test whether a relation has a system cache.
1502 */
1503bool
1504RelationHasSysCache(Oid relid)
1505{
1506 int low = 0,
1507 high = SysCacheRelationOidSize - 1;
1508
1509 while (low <= high)
1510 {
1511 int middle = low + (high - low) / 2;
1512
1513 if (SysCacheRelationOid[middle] == relid)
1514 return true;
1515 if (SysCacheRelationOid[middle] < relid)
1516 low = middle + 1;
1517 else
1518 high = middle - 1;
1519 }
1520
1521 return false;
1522}
1523
1524/*
1525 * Test whether a relation supports a system cache, ie it is either a
1526 * cached table or the index used for a cache.
1527 */
1528bool
1529RelationSupportsSysCache(Oid relid)
1530{
1531 int low = 0,
1532 high = SysCacheSupportingRelOidSize - 1;
1533
1534 while (low <= high)
1535 {
1536 int middle = low + (high - low) / 2;
1537
1538 if (SysCacheSupportingRelOid[middle] == relid)
1539 return true;
1540 if (SysCacheSupportingRelOid[middle] < relid)
1541 low = middle + 1;
1542 else
1543 high = middle - 1;
1544 }
1545
1546 return false;
1547}
1548
1549
1550/*
1551 * OID comparator for pg_qsort
1552 */
1553static int
1554oid_compare(const void *a, const void *b)
1555{
1556 Oid oa = *((const Oid *) a);
1557 Oid ob = *((const Oid *) b);
1558
1559 if (oa == ob)
1560 return 0;
1561 return (oa > ob) ? 1 : -1;
1562}
1563