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"
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_subscription.h"
66 #include "catalog/pg_subscription_rel.h"
67 #include "catalog/pg_tablespace.h"
68 #include "catalog/pg_transform.h"
69 #include "catalog/pg_ts_config.h"
70 #include "catalog/pg_ts_config_map.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"
75 #include "catalog/pg_user_mapping.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 */
125 AggregateFnoidIndexId,
126 1,
127 {
128 Anum_pg_aggregate_aggfnoid,
129 0,
130 0,
131 0
132 },
133 16
134 },
135 {AccessMethodRelationId, /* AMNAME */
136 AmNameIndexId,
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 {
150 ObjectIdAttributeNumber,
151 0,
152 0,
153 0
154 },
155 4
156 },
157 {AccessMethodOperatorRelationId, /* AMOPOPID */
158 AccessMethodOperatorIndexId,
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 */
169 AccessMethodStrategyIndexId,
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 */
180 AccessMethodProcedureIndexId,
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 */
191 AttributeRelidNameIndexId,
192 2,
193 {
194 Anum_pg_attribute_attrelid,
195 Anum_pg_attribute_attname,
196 0,
197 0
198 },
199 32
200 },
201 {AttributeRelationId, /* ATTNUM */
202 AttributeRelidNumIndexId,
203 2,
204 {
205 Anum_pg_attribute_attrelid,
206 Anum_pg_attribute_attnum,
207 0,
208 0
209 },
210 128
211 },
212 {AuthMemRelationId, /* AUTHMEMMEMROLE */
213 AuthMemMemRoleIndexId,
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 */
224 AuthMemRoleMemIndexId,
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 */
235 AuthIdRolnameIndexId,
236 1,
237 {
238 Anum_pg_authid_rolname,
239 0,
240 0,
241 0
242 },
243 8
244 },
245 {AuthIdRelationId, /* AUTHOID */
246 AuthIdOidIndexId,
247 1,
248 {
249 ObjectIdAttributeNumber,
250 0,
251 0,
252 0
253 },
254 8
255 },
256 {
257 CastRelationId, /* CASTSOURCETARGET */
258 CastSourceTargetIndexId,
259 2,
260 {
261 Anum_pg_cast_castsource,
262 Anum_pg_cast_casttarget,
263 0,
264 0
265 },
266 256
267 },
268 {OperatorClassRelationId, /* CLAAMNAMENSP */
269 OpclassAmNameNspIndexId,
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 */
280 OpclassOidIndexId,
281 1,
282 {
283 ObjectIdAttributeNumber,
284 0,
285 0,
286 0
287 },
288 8
289 },
290 {CollationRelationId, /* COLLNAMEENCNSP */
291 CollationNameEncNspIndexId,
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 */
302 CollationOidIndexId,
303 1,
304 {
305 ObjectIdAttributeNumber,
306 0,
307 0,
308 0
309 },
310 8
311 },
312 {ConversionRelationId, /* CONDEFAULT */
313 ConversionDefaultIndexId,
314 4,
315 {
316 Anum_pg_conversion_connamespace,
317 Anum_pg_conversion_conforencoding,
318 Anum_pg_conversion_contoencoding,
319 ObjectIdAttributeNumber,
320 },
321 8
322 },
323 {ConversionRelationId, /* CONNAMENSP */
324 ConversionNameNspIndexId,
325 2,
326 {
327 Anum_pg_conversion_conname,
328 Anum_pg_conversion_connamespace,
329 0,
330 0
331 },
332 8
333 },
334 {ConstraintRelationId, /* CONSTROID */
335 ConstraintOidIndexId,
336 1,
337 {
338 ObjectIdAttributeNumber,
339 0,
340 0,
341 0
342 },
343 16
344 },
345 {ConversionRelationId, /* CONVOID */
346 ConversionOidIndexId,
347 1,
348 {
349 ObjectIdAttributeNumber,
350 0,
351 0,
352 0
353 },
354 8
355 },
356 {DatabaseRelationId, /* DATABASEOID */
357 DatabaseOidIndexId,
358 1,
359 {
360 ObjectIdAttributeNumber,
361 0,
362 0,
363 0
364 },
365 4
366 },
367 {DefaultAclRelationId, /* DEFACLROLENSPOBJ */
368 DefaultAclRoleNspObjIndexId,
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 */
379 EnumOidIndexId,
380 1,
381 {
382 ObjectIdAttributeNumber,
383 0,
384 0,
385 0
386 },
387 8
388 },
389 {EnumRelationId, /* ENUMTYPOIDNAME */
390 EnumTypIdLabelIndexId,
391 2,
392 {
393 Anum_pg_enum_enumtypid,
394 Anum_pg_enum_enumlabel,
395 0,
396 0
397 },
398 8
399 },
400 {EventTriggerRelationId, /* EVENTTRIGGERNAME */
401 EventTriggerNameIndexId,
402 1,
403 {
404 Anum_pg_event_trigger_evtname,
405 0,
406 0,
407 0
408 },
409 8
410 },
411 {EventTriggerRelationId, /* EVENTTRIGGEROID */
412 EventTriggerOidIndexId,
413 1,
414 {
415 ObjectIdAttributeNumber,
416 0,
417 0,
418 0
419 },
420 8
421 },
422 {ForeignDataWrapperRelationId, /* FOREIGNDATAWRAPPERNAME */
423 ForeignDataWrapperNameIndexId,
424 1,
425 {
426 Anum_pg_foreign_data_wrapper_fdwname,
427 0,
428 0,
429 0
430 },
431 2
432 },
433 {ForeignDataWrapperRelationId, /* FOREIGNDATAWRAPPEROID */
434 ForeignDataWrapperOidIndexId,
435 1,
436 {
437 ObjectIdAttributeNumber,
438 0,
439 0,
440 0
441 },
442 2
443 },
444 {ForeignServerRelationId, /* FOREIGNSERVERNAME */
445 ForeignServerNameIndexId,
446 1,
447 {
448 Anum_pg_foreign_server_srvname,
449 0,
450 0,
451 0
452 },
453 2
454 },
455 {ForeignServerRelationId, /* FOREIGNSERVEROID */
456 ForeignServerOidIndexId,
457 1,
458 {
459 ObjectIdAttributeNumber,
460 0,
461 0,
462 0
463 },
464 2
465 },
466 {ForeignTableRelationId, /* FOREIGNTABLEREL */
467 ForeignTableRelidIndexId,
468 1,
469 {
470 Anum_pg_foreign_table_ftrelid,
471 0,
472 0,
473 0
474 },
475 4
476 },
477 {IndexRelationId, /* INDEXRELID */
478 IndexRelidIndexId,
479 1,
480 {
481 Anum_pg_index_indexrelid,
482 0,
483 0,
484 0
485 },
486 64
487 },
488 {LanguageRelationId, /* LANGNAME */
489 LanguageNameIndexId,
490 1,
491 {
492 Anum_pg_language_lanname,
493 0,
494 0,
495 0
496 },
497 4
498 },
499 {LanguageRelationId, /* LANGOID */
500 LanguageOidIndexId,
501 1,
502 {
503 ObjectIdAttributeNumber,
504 0,
505 0,
506 0
507 },
508 4
509 },
510 {NamespaceRelationId, /* NAMESPACENAME */
511 NamespaceNameIndexId,
512 1,
513 {
514 Anum_pg_namespace_nspname,
515 0,
516 0,
517 0
518 },
519 4
520 },
521 {NamespaceRelationId, /* NAMESPACEOID */
522 NamespaceOidIndexId,
523 1,
524 {
525 ObjectIdAttributeNumber,
526 0,
527 0,
528 0
529 },
530 16
531 },
532 {OperatorRelationId, /* OPERNAMENSP */
533 OperatorNameNspIndexId,
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 */
544 OperatorOidIndexId,
545 1,
546 {
547 ObjectIdAttributeNumber,
548 0,
549 0,
550 0
551 },
552 32
553 },
554 {OperatorFamilyRelationId, /* OPFAMILYAMNAMENSP */
555 OpfamilyAmNameNspIndexId,
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 */
566 OpfamilyOidIndexId,
567 1,
568 {
569 ObjectIdAttributeNumber,
570 0,
571 0,
572 0
573 },
574 8
575 },
576 {PartitionedRelationId, /* PARTRELID */
577 PartitionedRelidIndexId,
578 1,
579 {
580 Anum_pg_partitioned_table_partrelid,
581 0,
582 0,
583 0
584 },
585 32
586 },
587 {ProcedureRelationId, /* PROCNAMEARGSNSP */
588 ProcedureNameArgsNspIndexId,
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 */
599 ProcedureOidIndexId,
600 1,
601 {
602 ObjectIdAttributeNumber,
603 0,
604 0,
605 0
606 },
607 128
608 },
609 {PublicationRelationId, /* PUBLICATIONNAME */
610 PublicationNameIndexId,
611 1,
612 {
613 Anum_pg_publication_pubname,
614 0,
615 0,
616 0
617 },
618 8
619 },
620 {PublicationRelationId, /* PUBLICATIONOID */
621 PublicationObjectIndexId,
622 1,
623 {
624 ObjectIdAttributeNumber,
625 0,
626 0,
627 0
628 },
629 8
630 },
631 {PublicationRelRelationId, /* PUBLICATIONREL */
632 PublicationRelObjectIndexId,
633 1,
634 {
635 ObjectIdAttributeNumber,
636 0,
637 0,
638 0
639 },
640 64
641 },
642 {PublicationRelRelationId, /* PUBLICATIONRELMAP */
643 PublicationRelPrrelidPrpubidIndexId,
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 */
654 RangeTypidIndexId,
655 1,
656 {
657 Anum_pg_range_rngtypid,
658 0,
659 0,
660 0
661 },
662 4
663 },
664 {RelationRelationId, /* RELNAMENSP */
665 ClassNameNspIndexId,
666 2,
667 {
668 Anum_pg_class_relname,
669 Anum_pg_class_relnamespace,
670 0,
671 0
672 },
673 128
674 },
675 {RelationRelationId, /* RELOID */
676 ClassOidIndexId,
677 1,
678 {
679 ObjectIdAttributeNumber,
680 0,
681 0,
682 0
683 },
684 128
685 },
686 {ReplicationOriginRelationId, /* REPLORIGIDENT */
687 ReplicationOriginIdentIndex,
688 1,
689 {
690 Anum_pg_replication_origin_roident,
691 0,
692 0,
693 0
694 },
695 16
696 },
697 {ReplicationOriginRelationId, /* REPLORIGNAME */
698 ReplicationOriginNameIndex,
699 1,
700 {
701 Anum_pg_replication_origin_roname,
702 0,
703 0,
704 0
705 },
706 16
707 },
708 {RewriteRelationId, /* RULERELNAME */
709 RewriteRelRulenameIndexId,
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 */
720 SequenceRelidIndexId,
721 1,
722 {
723 Anum_pg_sequence_seqrelid,
724 0,
725 0,
726 0
727 },
728 32
729 },
730 {StatisticExtRelationId, /* STATEXTNAMENSP */
731 StatisticExtNameIndexId,
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 */
742 StatisticExtOidIndexId,
743 1,
744 {
745 ObjectIdAttributeNumber,
746 0,
747 0,
748 0
749 },
750 4
751 },
752 {StatisticRelationId, /* STATRELATTINH */
753 StatisticRelidAttnumInhIndexId,
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 */
764 SubscriptionNameIndexId,
765 2,
766 {
767 Anum_pg_subscription_subdbid,
768 Anum_pg_subscription_subname,
769 0,
770 0
771 },
772 4
773 },
774 {SubscriptionRelationId, /* SUBSCRIPTIONOID */
775 SubscriptionObjectIndexId,
776 1,
777 {
778 ObjectIdAttributeNumber,
779 0,
780 0,
781 0
782 },
783 4
784 },
785 {SubscriptionRelRelationId, /* SUBSCRIPTIONRELMAP */
786 SubscriptionRelSrrelidSrsubidIndexId,
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 */
797 TablespaceOidIndexId,
798 1,
799 {
800 ObjectIdAttributeNumber,
801 0,
802 0,
803 0,
804 },
805 4
806 },
807 {TransformRelationId, /* TRFOID */
808 TransformOidIndexId,
809 1,
810 {
811 ObjectIdAttributeNumber,
812 0,
813 0,
814 0,
815 },
816 16
817 },
818 {TransformRelationId, /* TRFTYPELANG */
819 TransformTypeLangIndexId,
820 2,
821 {
822 Anum_pg_transform_trftype,
823 Anum_pg_transform_trflang,
824 0,
825 0,
826 },
827 16
828 },
829 {TSConfigMapRelationId, /* TSCONFIGMAP */
830 TSConfigMapIndexId,
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 */
841 TSConfigNameNspIndexId,
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 */
852 TSConfigOidIndexId,
853 1,
854 {
855 ObjectIdAttributeNumber,
856 0,
857 0,
858 0
859 },
860 2
861 },
862 {TSDictionaryRelationId, /* TSDICTNAMENSP */
863 TSDictionaryNameNspIndexId,
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 */
874 TSDictionaryOidIndexId,
875 1,
876 {
877 ObjectIdAttributeNumber,
878 0,
879 0,
880 0
881 },
882 2
883 },
884 {TSParserRelationId, /* TSPARSERNAMENSP */
885 TSParserNameNspIndexId,
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 */
896 TSParserOidIndexId,
897 1,
898 {
899 ObjectIdAttributeNumber,
900 0,
901 0,
902 0
903 },
904 2
905 },
906 {TSTemplateRelationId, /* TSTEMPLATENAMENSP */
907 TSTemplateNameNspIndexId,
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 */
918 TSTemplateOidIndexId,
919 1,
920 {
921 ObjectIdAttributeNumber,
922 0,
923 0,
924 0
925 },
926 2
927 },
928 {TypeRelationId, /* TYPENAMENSP */
929 TypeNameNspIndexId,
930 2,
931 {
932 Anum_pg_type_typname,
933 Anum_pg_type_typnamespace,
934 0,
935 0
936 },
937 64
938 },
939 {TypeRelationId, /* TYPEOID */
940 TypeOidIndexId,
941 1,
942 {
943 ObjectIdAttributeNumber,
944 0,
945 0,
946 0
947 },
948 64
949 },
950 {UserMappingRelationId, /* USERMAPPINGOID */
951 UserMappingOidIndexId,
952 1,
953 {
954 ObjectIdAttributeNumber,
955 0,
956 0,
957 0
958 },
959 2
960 },
961 {UserMappingRelationId, /* USERMAPPINGUSERSERVER */
962 UserMappingUserServerIndexId,
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
974 static CatCache *SysCache[SysCacheSize];
975
976 static bool CacheInitialized = false;
977
978 /* Sorted array of OIDs of tables that have caches on them */
979 static Oid SysCacheRelationOid[SysCacheSize];
980 static int SysCacheRelationOidSize;
981
982 /* Sorted array of OIDs of tables and indexes used by caches */
983 static Oid SysCacheSupportingRelOid[SysCacheSize * 2];
984 static int SysCacheSupportingRelOidSize;
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
InitCatalogCache(void)998 InitCatalogCache(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
1007 Assert(!CacheInitialized);
1008
1009 SysCacheRelationOidSize = SysCacheSupportingRelOidSize = 0;
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 */
1023 SysCacheRelationOid[SysCacheRelationOidSize++] =
1024 cacheinfo[cacheId].reloid;
1025 SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
1026 cacheinfo[cacheId].reloid;
1027 SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
1028 cacheinfo[cacheId].indoid;
1029 /* see comments for RelationInvalidatesSnapshotsOnly */
1030 Assert(!RelationInvalidatesSnapshotsOnly(cacheinfo[cacheId].reloid));
1031 }
1032
1033 Assert(SysCacheRelationOidSize <= lengthof(SysCacheRelationOid));
1034 Assert(SysCacheSupportingRelOidSize <= lengthof(SysCacheSupportingRelOid));
1035
1036 /* Sort and de-dup OID arrays, so we can use binary search. */
1037 pg_qsort(SysCacheRelationOid, SysCacheRelationOidSize,
1038 sizeof(Oid), oid_compare);
1039 for (i = 1, j = 0; i < SysCacheRelationOidSize; i++)
1040 {
1041 if (SysCacheRelationOid[i] != SysCacheRelationOid[j])
1042 SysCacheRelationOid[++j] = SysCacheRelationOid[i];
1043 }
1044 SysCacheRelationOidSize = j + 1;
1045
1046 pg_qsort(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
1047 sizeof(Oid), oid_compare);
1048 for (i = 1, j = 0; i < SysCacheSupportingRelOidSize; i++)
1049 {
1050 if (SysCacheSupportingRelOid[i] != SysCacheSupportingRelOid[j])
1051 SysCacheSupportingRelOid[++j] = SysCacheSupportingRelOid[i];
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
InitCatalogCachePhase2(void)1071 InitCatalogCachePhase2(void)
1072 {
1073 int cacheId;
1074
1075 Assert(CacheInitialized);
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
SearchSysCache(int cacheId,Datum key1,Datum key2,Datum key3,Datum key4)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
SearchSysCache1(int cacheId,Datum key1)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
SearchSysCache2(int cacheId,Datum key1,Datum key2)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
SearchSysCache3(int cacheId,Datum key1,Datum key2,Datum key3)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
SearchSysCache4(int cacheId,Datum key1,Datum key2,Datum key3,Datum key4)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
ReleaseSysCache(HeapTuple tuple)1160 ReleaseSysCache(HeapTuple tuple)
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
SearchSysCacheCopy(int cacheId,Datum key1,Datum key2,Datum key3,Datum key4)1174 SearchSysCacheCopy(int cacheId,
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
SearchSysCacheExists(int cacheId,Datum key1,Datum key2,Datum key3,Datum key4)1198 SearchSysCacheExists(int cacheId,
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
GetSysCacheOid(int cacheId,Datum key1,Datum key2,Datum key3,Datum key4)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
SearchSysCacheAttName(Oid relid,const char * attname)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
SearchSysCacheCopyAttName(Oid relid,const char * attname)1271 SearchSysCacheCopyAttName(Oid relid, const char *attname)
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
SearchSysCacheExistsAttName(Oid relid,const char * attname)1290 SearchSysCacheExistsAttName(Oid relid, const char *attname)
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
SearchSysCacheAttNum(Oid relid,int16 attnum)1311 SearchSysCacheAttNum(Oid relid, int16 attnum)
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
SearchSysCacheCopyAttNum(Oid relid,int16 attnum)1334 SearchSysCacheCopyAttNum(Oid relid, int16 attnum)
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
SysCacheGetAttr(int cacheId,HeapTuple tup,AttrNumber attributeNumber,bool * isNull)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
GetSysCacheHashValue(int cacheId,Datum key1,Datum key2,Datum key3,Datum key4)1403 GetSysCacheHashValue(int cacheId,
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 *
SearchSysCacheList(int cacheId,int nkeys,Datum key1,Datum key2,Datum key3)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
SysCacheInvalidate(int cacheId,uint32 hashValue)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
RelationInvalidatesSnapshotsOnly(Oid relid)1464 RelationInvalidatesSnapshotsOnly(Oid relid)
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
RelationHasSysCache(Oid relid)1487 RelationHasSysCache(Oid relid)
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
RelationSupportsSysCache(Oid relid)1512 RelationSupportsSysCache(Oid relid)
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
oid_compare(const void * a,const void * b)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 }
1546