1 /*-------------------------------------------------------------------------
2 *
3 * syscache.c
4 * System cache management routines
5 *
6 * Portions Copyright (c) 1996-2020, 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_replication_origin.h"
57 #include "catalog/pg_rewrite.h"
58 #include "catalog/pg_seclabel.h"
59 #include "catalog/pg_sequence.h"
60 #include "catalog/pg_shdepend.h"
61 #include "catalog/pg_shdescription.h"
62 #include "catalog/pg_shseclabel.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 "lib/qunique.h"
78 #include "utils/catcache.h"
79 #include "utils/rel.h"
80 #include "utils/syscache.h"
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 */
115 struct 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
124 static 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
986 static CatCache *SysCache[SysCacheSize];
987
988 static bool CacheInitialized = false;
989
990 /* Sorted array of OIDs of tables that have caches on them */
991 static Oid SysCacheRelationOid[SysCacheSize];
992 static int SysCacheRelationOidSize;
993
994 /* Sorted array of OIDs of tables and indexes used by caches */
995 static Oid SysCacheSupportingRelOid[SysCacheSize * 2];
996 static int SysCacheSupportingRelOidSize;
997
998 static 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 */
1009 void
InitCatalogCache(void)1010 InitCatalogCache(void)
1011 {
1012 int cacheId;
1013
1014 StaticAssertStmt(SysCacheSize == (int) lengthof(cacheinfo),
1015 "SysCacheSize does not match syscache.c's array");
1016
1017 Assert(!CacheInitialized);
1018
1019 SysCacheRelationOidSize = SysCacheSupportingRelOidSize = 0;
1020
1021 for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
1022 {
1023 SysCache[cacheId] = InitCatCache(cacheId,
1024 cacheinfo[cacheId].reloid,
1025 cacheinfo[cacheId].indoid,
1026 cacheinfo[cacheId].nkeys,
1027 cacheinfo[cacheId].key,
1028 cacheinfo[cacheId].nbuckets);
1029 if (!PointerIsValid(SysCache[cacheId]))
1030 elog(ERROR, "could not initialize cache %u (%d)",
1031 cacheinfo[cacheId].reloid, cacheId);
1032 /* Accumulate data for OID lists, too */
1033 SysCacheRelationOid[SysCacheRelationOidSize++] =
1034 cacheinfo[cacheId].reloid;
1035 SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
1036 cacheinfo[cacheId].reloid;
1037 SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
1038 cacheinfo[cacheId].indoid;
1039 /* see comments for RelationInvalidatesSnapshotsOnly */
1040 Assert(!RelationInvalidatesSnapshotsOnly(cacheinfo[cacheId].reloid));
1041 }
1042
1043 Assert(SysCacheRelationOidSize <= lengthof(SysCacheRelationOid));
1044 Assert(SysCacheSupportingRelOidSize <= lengthof(SysCacheSupportingRelOid));
1045
1046 /* Sort and de-dup OID arrays, so we can use binary search. */
1047 pg_qsort(SysCacheRelationOid, SysCacheRelationOidSize,
1048 sizeof(Oid), oid_compare);
1049 SysCacheRelationOidSize =
1050 qunique(SysCacheRelationOid, SysCacheRelationOidSize, sizeof(Oid),
1051 oid_compare);
1052
1053 pg_qsort(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
1054 sizeof(Oid), oid_compare);
1055 SysCacheSupportingRelOidSize =
1056 qunique(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
1057 sizeof(Oid), oid_compare);
1058
1059 CacheInitialized = true;
1060 }
1061
1062 /*
1063 * InitCatalogCachePhase2 - finish initializing the caches
1064 *
1065 * Finish initializing all the caches, including necessary database
1066 * access.
1067 *
1068 * This is *not* essential; normally we allow syscaches to be initialized
1069 * on first use. However, it is useful as a mechanism to preload the
1070 * relcache with entries for the most-commonly-used system catalogs.
1071 * Therefore, we invoke this routine when we need to write a new relcache
1072 * init file.
1073 */
1074 void
InitCatalogCachePhase2(void)1075 InitCatalogCachePhase2(void)
1076 {
1077 int cacheId;
1078
1079 Assert(CacheInitialized);
1080
1081 for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
1082 InitCatCachePhase2(SysCache[cacheId], true);
1083 }
1084
1085
1086 /*
1087 * SearchSysCache
1088 *
1089 * A layer on top of SearchCatCache that does the initialization and
1090 * key-setting for you.
1091 *
1092 * Returns the cache copy of the tuple if one is found, NULL if not.
1093 * The tuple is the 'cache' copy and must NOT be modified!
1094 *
1095 * When the caller is done using the tuple, call ReleaseSysCache()
1096 * to release the reference count grabbed by SearchSysCache(). If this
1097 * is not done, the tuple will remain locked in cache until end of
1098 * transaction, which is tolerable but not desirable.
1099 *
1100 * CAUTION: The tuple that is returned must NOT be freed by the caller!
1101 */
1102 HeapTuple
SearchSysCache(int cacheId,Datum key1,Datum key2,Datum key3,Datum key4)1103 SearchSysCache(int cacheId,
1104 Datum key1,
1105 Datum key2,
1106 Datum key3,
1107 Datum key4)
1108 {
1109 Assert(cacheId >= 0 && cacheId < SysCacheSize &&
1110 PointerIsValid(SysCache[cacheId]));
1111
1112 return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
1113 }
1114
1115 HeapTuple
SearchSysCache1(int cacheId,Datum key1)1116 SearchSysCache1(int cacheId,
1117 Datum key1)
1118 {
1119 Assert(cacheId >= 0 && cacheId < SysCacheSize &&
1120 PointerIsValid(SysCache[cacheId]));
1121 Assert(SysCache[cacheId]->cc_nkeys == 1);
1122
1123 return SearchCatCache1(SysCache[cacheId], key1);
1124 }
1125
1126 HeapTuple
SearchSysCache2(int cacheId,Datum key1,Datum key2)1127 SearchSysCache2(int cacheId,
1128 Datum key1, Datum key2)
1129 {
1130 Assert(cacheId >= 0 && cacheId < SysCacheSize &&
1131 PointerIsValid(SysCache[cacheId]));
1132 Assert(SysCache[cacheId]->cc_nkeys == 2);
1133
1134 return SearchCatCache2(SysCache[cacheId], key1, key2);
1135 }
1136
1137 HeapTuple
SearchSysCache3(int cacheId,Datum key1,Datum key2,Datum key3)1138 SearchSysCache3(int cacheId,
1139 Datum key1, Datum key2, Datum key3)
1140 {
1141 Assert(cacheId >= 0 && cacheId < SysCacheSize &&
1142 PointerIsValid(SysCache[cacheId]));
1143 Assert(SysCache[cacheId]->cc_nkeys == 3);
1144
1145 return SearchCatCache3(SysCache[cacheId], key1, key2, key3);
1146 }
1147
1148 HeapTuple
SearchSysCache4(int cacheId,Datum key1,Datum key2,Datum key3,Datum key4)1149 SearchSysCache4(int cacheId,
1150 Datum key1, Datum key2, Datum key3, Datum key4)
1151 {
1152 Assert(cacheId >= 0 && cacheId < SysCacheSize &&
1153 PointerIsValid(SysCache[cacheId]));
1154 Assert(SysCache[cacheId]->cc_nkeys == 4);
1155
1156 return SearchCatCache4(SysCache[cacheId], key1, key2, key3, key4);
1157 }
1158
1159 /*
1160 * ReleaseSysCache
1161 * Release previously grabbed reference count on a tuple
1162 */
1163 void
ReleaseSysCache(HeapTuple tuple)1164 ReleaseSysCache(HeapTuple tuple)
1165 {
1166 ReleaseCatCache(tuple);
1167 }
1168
1169 /*
1170 * SearchSysCacheCopy
1171 *
1172 * A convenience routine that does SearchSysCache and (if successful)
1173 * returns a modifiable copy of the syscache entry. The original
1174 * syscache entry is released before returning. The caller should
1175 * heap_freetuple() the result when done with it.
1176 */
1177 HeapTuple
SearchSysCacheCopy(int cacheId,Datum key1,Datum key2,Datum key3,Datum key4)1178 SearchSysCacheCopy(int cacheId,
1179 Datum key1,
1180 Datum key2,
1181 Datum key3,
1182 Datum key4)
1183 {
1184 HeapTuple tuple,
1185 newtuple;
1186
1187 tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1188 if (!HeapTupleIsValid(tuple))
1189 return tuple;
1190 newtuple = heap_copytuple(tuple);
1191 ReleaseSysCache(tuple);
1192 return newtuple;
1193 }
1194
1195 /*
1196 * SearchSysCacheExists
1197 *
1198 * A convenience routine that just probes to see if a tuple can be found.
1199 * No lock is retained on the syscache entry.
1200 */
1201 bool
SearchSysCacheExists(int cacheId,Datum key1,Datum key2,Datum key3,Datum key4)1202 SearchSysCacheExists(int cacheId,
1203 Datum key1,
1204 Datum key2,
1205 Datum key3,
1206 Datum key4)
1207 {
1208 HeapTuple tuple;
1209
1210 tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1211 if (!HeapTupleIsValid(tuple))
1212 return false;
1213 ReleaseSysCache(tuple);
1214 return true;
1215 }
1216
1217 /*
1218 * GetSysCacheOid
1219 *
1220 * A convenience routine that does SearchSysCache and returns the OID in the
1221 * oidcol column of the found tuple, or InvalidOid if no tuple could be found.
1222 * No lock is retained on the syscache entry.
1223 */
1224 Oid
GetSysCacheOid(int cacheId,AttrNumber oidcol,Datum key1,Datum key2,Datum key3,Datum key4)1225 GetSysCacheOid(int cacheId,
1226 AttrNumber oidcol,
1227 Datum key1,
1228 Datum key2,
1229 Datum key3,
1230 Datum key4)
1231 {
1232 HeapTuple tuple;
1233 bool isNull;
1234 Oid result;
1235
1236 tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1237 if (!HeapTupleIsValid(tuple))
1238 return InvalidOid;
1239 result = heap_getattr(tuple, oidcol,
1240 SysCache[cacheId]->cc_tupdesc,
1241 &isNull);
1242 Assert(!isNull); /* columns used as oids should never be NULL */
1243 ReleaseSysCache(tuple);
1244 return result;
1245 }
1246
1247
1248 /*
1249 * SearchSysCacheAttName
1250 *
1251 * This routine is equivalent to SearchSysCache on the ATTNAME cache,
1252 * except that it will return NULL if the found attribute is marked
1253 * attisdropped. This is convenient for callers that want to act as
1254 * though dropped attributes don't exist.
1255 */
1256 HeapTuple
SearchSysCacheAttName(Oid relid,const char * attname)1257 SearchSysCacheAttName(Oid relid, const char *attname)
1258 {
1259 HeapTuple tuple;
1260
1261 tuple = SearchSysCache2(ATTNAME,
1262 ObjectIdGetDatum(relid),
1263 CStringGetDatum(attname));
1264 if (!HeapTupleIsValid(tuple))
1265 return NULL;
1266 if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
1267 {
1268 ReleaseSysCache(tuple);
1269 return NULL;
1270 }
1271 return tuple;
1272 }
1273
1274 /*
1275 * SearchSysCacheCopyAttName
1276 *
1277 * As above, an attisdropped-aware version of SearchSysCacheCopy.
1278 */
1279 HeapTuple
SearchSysCacheCopyAttName(Oid relid,const char * attname)1280 SearchSysCacheCopyAttName(Oid relid, const char *attname)
1281 {
1282 HeapTuple tuple,
1283 newtuple;
1284
1285 tuple = SearchSysCacheAttName(relid, attname);
1286 if (!HeapTupleIsValid(tuple))
1287 return tuple;
1288 newtuple = heap_copytuple(tuple);
1289 ReleaseSysCache(tuple);
1290 return newtuple;
1291 }
1292
1293 /*
1294 * SearchSysCacheExistsAttName
1295 *
1296 * As above, an attisdropped-aware version of SearchSysCacheExists.
1297 */
1298 bool
SearchSysCacheExistsAttName(Oid relid,const char * attname)1299 SearchSysCacheExistsAttName(Oid relid, const char *attname)
1300 {
1301 HeapTuple tuple;
1302
1303 tuple = SearchSysCacheAttName(relid, attname);
1304 if (!HeapTupleIsValid(tuple))
1305 return false;
1306 ReleaseSysCache(tuple);
1307 return true;
1308 }
1309
1310
1311 /*
1312 * SearchSysCacheAttNum
1313 *
1314 * This routine is equivalent to SearchSysCache on the ATTNUM cache,
1315 * except that it will return NULL if the found attribute is marked
1316 * attisdropped. This is convenient for callers that want to act as
1317 * though dropped attributes don't exist.
1318 */
1319 HeapTuple
SearchSysCacheAttNum(Oid relid,int16 attnum)1320 SearchSysCacheAttNum(Oid relid, int16 attnum)
1321 {
1322 HeapTuple tuple;
1323
1324 tuple = SearchSysCache2(ATTNUM,
1325 ObjectIdGetDatum(relid),
1326 Int16GetDatum(attnum));
1327 if (!HeapTupleIsValid(tuple))
1328 return NULL;
1329 if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
1330 {
1331 ReleaseSysCache(tuple);
1332 return NULL;
1333 }
1334 return tuple;
1335 }
1336
1337 /*
1338 * SearchSysCacheCopyAttNum
1339 *
1340 * As above, an attisdropped-aware version of SearchSysCacheCopy.
1341 */
1342 HeapTuple
SearchSysCacheCopyAttNum(Oid relid,int16 attnum)1343 SearchSysCacheCopyAttNum(Oid relid, int16 attnum)
1344 {
1345 HeapTuple tuple,
1346 newtuple;
1347
1348 tuple = SearchSysCacheAttNum(relid, attnum);
1349 if (!HeapTupleIsValid(tuple))
1350 return NULL;
1351 newtuple = heap_copytuple(tuple);
1352 ReleaseSysCache(tuple);
1353 return newtuple;
1354 }
1355
1356
1357 /*
1358 * SysCacheGetAttr
1359 *
1360 * Given a tuple previously fetched by SearchSysCache(),
1361 * extract a specific attribute.
1362 *
1363 * This is equivalent to using heap_getattr() on a tuple fetched
1364 * from a non-cached relation. Usually, this is only used for attributes
1365 * that could be NULL or variable length; the fixed-size attributes in
1366 * a system table are accessed just by mapping the tuple onto the C struct
1367 * declarations from include/catalog/.
1368 *
1369 * As with heap_getattr(), if the attribute is of a pass-by-reference type
1370 * then a pointer into the tuple data area is returned --- the caller must
1371 * not modify or pfree the datum!
1372 *
1373 * Note: it is legal to use SysCacheGetAttr() with a cacheId referencing
1374 * a different cache for the same catalog the tuple was fetched from.
1375 */
1376 Datum
SysCacheGetAttr(int cacheId,HeapTuple tup,AttrNumber attributeNumber,bool * isNull)1377 SysCacheGetAttr(int cacheId, HeapTuple tup,
1378 AttrNumber attributeNumber,
1379 bool *isNull)
1380 {
1381 /*
1382 * We just need to get the TupleDesc out of the cache entry, and then we
1383 * can apply heap_getattr(). Normally the cache control data is already
1384 * valid (because the caller recently fetched the tuple via this same
1385 * cache), but there are cases where we have to initialize the cache here.
1386 */
1387 if (cacheId < 0 || cacheId >= SysCacheSize ||
1388 !PointerIsValid(SysCache[cacheId]))
1389 elog(ERROR, "invalid cache ID: %d", cacheId);
1390 if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
1391 {
1392 InitCatCachePhase2(SysCache[cacheId], false);
1393 Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
1394 }
1395
1396 return heap_getattr(tup, attributeNumber,
1397 SysCache[cacheId]->cc_tupdesc,
1398 isNull);
1399 }
1400
1401 /*
1402 * GetSysCacheHashValue
1403 *
1404 * Get the hash value that would be used for a tuple in the specified cache
1405 * with the given search keys.
1406 *
1407 * The reason for exposing this as part of the API is that the hash value is
1408 * exposed in cache invalidation operations, so there are places outside the
1409 * catcache code that need to be able to compute the hash values.
1410 */
1411 uint32
GetSysCacheHashValue(int cacheId,Datum key1,Datum key2,Datum key3,Datum key4)1412 GetSysCacheHashValue(int cacheId,
1413 Datum key1,
1414 Datum key2,
1415 Datum key3,
1416 Datum key4)
1417 {
1418 if (cacheId < 0 || cacheId >= SysCacheSize ||
1419 !PointerIsValid(SysCache[cacheId]))
1420 elog(ERROR, "invalid cache ID: %d", cacheId);
1421
1422 return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
1423 }
1424
1425 /*
1426 * List-search interface
1427 */
1428 struct catclist *
SearchSysCacheList(int cacheId,int nkeys,Datum key1,Datum key2,Datum key3)1429 SearchSysCacheList(int cacheId, int nkeys,
1430 Datum key1, Datum key2, Datum key3)
1431 {
1432 if (cacheId < 0 || cacheId >= SysCacheSize ||
1433 !PointerIsValid(SysCache[cacheId]))
1434 elog(ERROR, "invalid cache ID: %d", cacheId);
1435
1436 return SearchCatCacheList(SysCache[cacheId], nkeys,
1437 key1, key2, key3);
1438 }
1439
1440 /*
1441 * SysCacheInvalidate
1442 *
1443 * Invalidate entries in the specified cache, given a hash value.
1444 * See CatCacheInvalidate() for more info.
1445 *
1446 * This routine is only quasi-public: it should only be used by inval.c.
1447 */
1448 void
SysCacheInvalidate(int cacheId,uint32 hashValue)1449 SysCacheInvalidate(int cacheId, uint32 hashValue)
1450 {
1451 if (cacheId < 0 || cacheId >= SysCacheSize)
1452 elog(ERROR, "invalid cache ID: %d", cacheId);
1453
1454 /* if this cache isn't initialized yet, no need to do anything */
1455 if (!PointerIsValid(SysCache[cacheId]))
1456 return;
1457
1458 CatCacheInvalidate(SysCache[cacheId], hashValue);
1459 }
1460
1461 /*
1462 * Certain relations that do not have system caches send snapshot invalidation
1463 * messages in lieu of catcache messages. This is for the benefit of
1464 * GetCatalogSnapshot(), which can then reuse its existing MVCC snapshot
1465 * for scanning one of those catalogs, rather than taking a new one, if no
1466 * invalidation has been received.
1467 *
1468 * Relations that have syscaches need not (and must not) be listed here. The
1469 * catcache invalidation messages will also flush the snapshot. If you add a
1470 * syscache for one of these relations, remove it from this list.
1471 */
1472 bool
RelationInvalidatesSnapshotsOnly(Oid relid)1473 RelationInvalidatesSnapshotsOnly(Oid relid)
1474 {
1475 switch (relid)
1476 {
1477 case DbRoleSettingRelationId:
1478 case DependRelationId:
1479 case SharedDependRelationId:
1480 case DescriptionRelationId:
1481 case SharedDescriptionRelationId:
1482 case SecLabelRelationId:
1483 case SharedSecLabelRelationId:
1484 return true;
1485 default:
1486 break;
1487 }
1488
1489 return false;
1490 }
1491
1492 /*
1493 * Test whether a relation has a system cache.
1494 */
1495 bool
RelationHasSysCache(Oid relid)1496 RelationHasSysCache(Oid relid)
1497 {
1498 int low = 0,
1499 high = SysCacheRelationOidSize - 1;
1500
1501 while (low <= high)
1502 {
1503 int middle = low + (high - low) / 2;
1504
1505 if (SysCacheRelationOid[middle] == relid)
1506 return true;
1507 if (SysCacheRelationOid[middle] < relid)
1508 low = middle + 1;
1509 else
1510 high = middle - 1;
1511 }
1512
1513 return false;
1514 }
1515
1516 /*
1517 * Test whether a relation supports a system cache, ie it is either a
1518 * cached table or the index used for a cache.
1519 */
1520 bool
RelationSupportsSysCache(Oid relid)1521 RelationSupportsSysCache(Oid relid)
1522 {
1523 int low = 0,
1524 high = SysCacheSupportingRelOidSize - 1;
1525
1526 while (low <= high)
1527 {
1528 int middle = low + (high - low) / 2;
1529
1530 if (SysCacheSupportingRelOid[middle] == relid)
1531 return true;
1532 if (SysCacheSupportingRelOid[middle] < relid)
1533 low = middle + 1;
1534 else
1535 high = middle - 1;
1536 }
1537
1538 return false;
1539 }
1540
1541
1542 /*
1543 * OID comparator for pg_qsort
1544 */
1545 static int
oid_compare(const void * a,const void * b)1546 oid_compare(const void *a, const void *b)
1547 {
1548 Oid oa = *((const Oid *) a);
1549 Oid ob = *((const Oid *) b);
1550
1551 if (oa == ob)
1552 return 0;
1553 return (oa > ob) ? 1 : -1;
1554 }
1555