Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * syscache.c
4 : * System cache management routines
5 : *
6 : * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/utils/cache/syscache.c
12 : *
13 : * NOTES
14 : * These routines allow the parser/planner/executor to perform
15 : * rapid lookups on the contents of the system catalogs.
16 : *
17 : * see utils/syscache.h for a list of the cache IDs
18 : *
19 : *-------------------------------------------------------------------------
20 : */
21 : #include "postgres.h"
22 :
23 : #include "access/htup_details.h"
24 : #include "access/sysattr.h"
25 : #include "catalog/indexing.h"
26 : #include "catalog/pg_aggregate.h"
27 : #include "catalog/pg_am.h"
28 : #include "catalog/pg_amop.h"
29 : #include "catalog/pg_amproc.h"
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
998 338 : 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 338 : Assert(!CacheInitialized);
1008 :
1009 338 : SysCacheRelationOidSize = SysCacheSupportingRelOidSize = 0;
1010 :
1011 26364 : for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
1012 : {
1013 52052 : SysCache[cacheId] = InitCatCache(cacheId,
1014 : cacheinfo[cacheId].reloid,
1015 : cacheinfo[cacheId].indoid,
1016 : cacheinfo[cacheId].nkeys,
1017 26026 : cacheinfo[cacheId].key,
1018 : cacheinfo[cacheId].nbuckets);
1019 26026 : if (!PointerIsValid(SysCache[cacheId]))
1020 0 : elog(ERROR, "could not initialize cache %u (%d)",
1021 : cacheinfo[cacheId].reloid, cacheId);
1022 : /* Accumulate data for OID lists, too */
1023 52052 : SysCacheRelationOid[SysCacheRelationOidSize++] =
1024 26026 : cacheinfo[cacheId].reloid;
1025 52052 : SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
1026 26026 : cacheinfo[cacheId].reloid;
1027 52052 : SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
1028 26026 : cacheinfo[cacheId].indoid;
1029 : /* see comments for RelationInvalidatesSnapshotsOnly */
1030 26026 : Assert(!RelationInvalidatesSnapshotsOnly(cacheinfo[cacheId].reloid));
1031 : }
1032 :
1033 338 : Assert(SysCacheRelationOidSize <= lengthof(SysCacheRelationOid));
1034 338 : Assert(SysCacheSupportingRelOidSize <= lengthof(SysCacheSupportingRelOid));
1035 :
1036 : /* Sort and de-dup OID arrays, so we can use binary search. */
1037 338 : pg_qsort(SysCacheRelationOid, SysCacheRelationOidSize,
1038 : sizeof(Oid), oid_compare);
1039 26026 : for (i = 1, j = 0; i < SysCacheRelationOidSize; i++)
1040 : {
1041 25688 : if (SysCacheRelationOid[i] != SysCacheRelationOid[j])
1042 15210 : SysCacheRelationOid[++j] = SysCacheRelationOid[i];
1043 : }
1044 338 : SysCacheRelationOidSize = j + 1;
1045 :
1046 338 : pg_qsort(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
1047 : sizeof(Oid), oid_compare);
1048 52052 : for (i = 1, j = 0; i < SysCacheSupportingRelOidSize; i++)
1049 : {
1050 51714 : if (SysCacheSupportingRelOid[i] != SysCacheSupportingRelOid[j])
1051 41236 : SysCacheSupportingRelOid[++j] = SysCacheSupportingRelOid[i];
1052 : }
1053 338 : SysCacheSupportingRelOidSize = j + 1;
1054 :
1055 338 : CacheInitialized = true;
1056 338 : }
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
1071 9 : InitCatalogCachePhase2(void)
1072 : {
1073 : int cacheId;
1074 :
1075 9 : Assert(CacheInitialized);
1076 :
1077 702 : for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
1078 693 : InitCatCachePhase2(SysCache[cacheId], true);
1079 9 : }
1080 :
1081 :
1082 : /*
1083 : * SearchSysCache
1084 : *
1085 : * A layer on top of SearchCatCache that does the initialization and
1086 : * key-setting for you.
1087 : *
1088 : * Returns the cache copy of the tuple if one is found, NULL if not.
1089 : * The tuple is the 'cache' copy and must NOT be modified!
1090 : *
1091 : * When the caller is done using the tuple, call ReleaseSysCache()
1092 : * to release the reference count grabbed by SearchSysCache(). If this
1093 : * is not done, the tuple will remain locked in cache until end of
1094 : * transaction, which is tolerable but not desirable.
1095 : *
1096 : * CAUTION: The tuple that is returned must NOT be freed by the caller!
1097 : */
1098 : HeapTuple
1099 2129059 : SearchSysCache(int cacheId,
1100 : Datum key1,
1101 : Datum key2,
1102 : Datum key3,
1103 : Datum key4)
1104 : {
1105 4258118 : if (cacheId < 0 || cacheId >= SysCacheSize ||
1106 2129059 : !PointerIsValid(SysCache[cacheId]))
1107 0 : elog(ERROR, "invalid cache ID: %d", cacheId);
1108 :
1109 2129059 : return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
1110 : }
1111 :
1112 : /*
1113 : * ReleaseSysCache
1114 : * Release previously grabbed reference count on a tuple
1115 : */
1116 : void
1117 1931681 : ReleaseSysCache(HeapTuple tuple)
1118 : {
1119 1931681 : ReleaseCatCache(tuple);
1120 1931681 : }
1121 :
1122 : /*
1123 : * SearchSysCacheCopy
1124 : *
1125 : * A convenience routine that does SearchSysCache and (if successful)
1126 : * returns a modifiable copy of the syscache entry. The original
1127 : * syscache entry is released before returning. The caller should
1128 : * heap_freetuple() the result when done with it.
1129 : */
1130 : HeapTuple
1131 15637 : SearchSysCacheCopy(int cacheId,
1132 : Datum key1,
1133 : Datum key2,
1134 : Datum key3,
1135 : Datum key4)
1136 : {
1137 : HeapTuple tuple,
1138 : newtuple;
1139 :
1140 15637 : tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1141 15637 : if (!HeapTupleIsValid(tuple))
1142 5090 : return tuple;
1143 10547 : newtuple = heap_copytuple(tuple);
1144 10547 : ReleaseSysCache(tuple);
1145 10547 : return newtuple;
1146 : }
1147 :
1148 : /*
1149 : * SearchSysCacheExists
1150 : *
1151 : * A convenience routine that just probes to see if a tuple can be found.
1152 : * No lock is retained on the syscache entry.
1153 : */
1154 : bool
1155 32078 : SearchSysCacheExists(int cacheId,
1156 : Datum key1,
1157 : Datum key2,
1158 : Datum key3,
1159 : Datum key4)
1160 : {
1161 : HeapTuple tuple;
1162 :
1163 32078 : tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1164 32078 : if (!HeapTupleIsValid(tuple))
1165 8301 : return false;
1166 23777 : ReleaseSysCache(tuple);
1167 23777 : return true;
1168 : }
1169 :
1170 : /*
1171 : * GetSysCacheOid
1172 : *
1173 : * A convenience routine that does SearchSysCache and returns the OID
1174 : * of the found tuple, or InvalidOid if no tuple could be found.
1175 : * No lock is retained on the syscache entry.
1176 : */
1177 : Oid
1178 119951 : GetSysCacheOid(int cacheId,
1179 : Datum key1,
1180 : Datum key2,
1181 : Datum key3,
1182 : Datum key4)
1183 : {
1184 : HeapTuple tuple;
1185 : Oid result;
1186 :
1187 119951 : tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1188 119951 : if (!HeapTupleIsValid(tuple))
1189 47853 : return InvalidOid;
1190 72098 : result = HeapTupleGetOid(tuple);
1191 72098 : ReleaseSysCache(tuple);
1192 72098 : return result;
1193 : }
1194 :
1195 :
1196 : /*
1197 : * SearchSysCacheAttName
1198 : *
1199 : * This routine is equivalent to SearchSysCache on the ATTNAME cache,
1200 : * except that it will return NULL if the found attribute is marked
1201 : * attisdropped. This is convenient for callers that want to act as
1202 : * though dropped attributes don't exist.
1203 : */
1204 : HeapTuple
1205 2397 : SearchSysCacheAttName(Oid relid, const char *attname)
1206 : {
1207 : HeapTuple tuple;
1208 :
1209 2397 : tuple = SearchSysCache2(ATTNAME,
1210 : ObjectIdGetDatum(relid),
1211 : CStringGetDatum(attname));
1212 2397 : if (!HeapTupleIsValid(tuple))
1213 104 : return NULL;
1214 2293 : if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
1215 : {
1216 13 : ReleaseSysCache(tuple);
1217 13 : return NULL;
1218 : }
1219 2280 : return tuple;
1220 : }
1221 :
1222 : /*
1223 : * SearchSysCacheCopyAttName
1224 : *
1225 : * As above, an attisdropped-aware version of SearchSysCacheCopy.
1226 : */
1227 : HeapTuple
1228 463 : SearchSysCacheCopyAttName(Oid relid, const char *attname)
1229 : {
1230 : HeapTuple tuple,
1231 : newtuple;
1232 :
1233 463 : tuple = SearchSysCacheAttName(relid, attname);
1234 463 : if (!HeapTupleIsValid(tuple))
1235 56 : return tuple;
1236 407 : newtuple = heap_copytuple(tuple);
1237 407 : ReleaseSysCache(tuple);
1238 407 : return newtuple;
1239 : }
1240 :
1241 : /*
1242 : * SearchSysCacheExistsAttName
1243 : *
1244 : * As above, an attisdropped-aware version of SearchSysCacheExists.
1245 : */
1246 : bool
1247 24 : SearchSysCacheExistsAttName(Oid relid, const char *attname)
1248 : {
1249 : HeapTuple tuple;
1250 :
1251 24 : tuple = SearchSysCacheAttName(relid, attname);
1252 24 : if (!HeapTupleIsValid(tuple))
1253 2 : return false;
1254 22 : ReleaseSysCache(tuple);
1255 22 : return true;
1256 : }
1257 :
1258 :
1259 : /*
1260 : * SysCacheGetAttr
1261 : *
1262 : * Given a tuple previously fetched by SearchSysCache(),
1263 : * extract a specific attribute.
1264 : *
1265 : * This is equivalent to using heap_getattr() on a tuple fetched
1266 : * from a non-cached relation. Usually, this is only used for attributes
1267 : * that could be NULL or variable length; the fixed-size attributes in
1268 : * a system table are accessed just by mapping the tuple onto the C struct
1269 : * declarations from include/catalog/.
1270 : *
1271 : * As with heap_getattr(), if the attribute is of a pass-by-reference type
1272 : * then a pointer into the tuple data area is returned --- the caller must
1273 : * not modify or pfree the datum!
1274 : *
1275 : * Note: it is legal to use SysCacheGetAttr() with a cacheId referencing
1276 : * a different cache for the same catalog the tuple was fetched from.
1277 : */
1278 : Datum
1279 73656 : SysCacheGetAttr(int cacheId, HeapTuple tup,
1280 : AttrNumber attributeNumber,
1281 : bool *isNull)
1282 : {
1283 : /*
1284 : * We just need to get the TupleDesc out of the cache entry, and then we
1285 : * can apply heap_getattr(). Normally the cache control data is already
1286 : * valid (because the caller recently fetched the tuple via this same
1287 : * cache), but there are cases where we have to initialize the cache here.
1288 : */
1289 147312 : if (cacheId < 0 || cacheId >= SysCacheSize ||
1290 73656 : !PointerIsValid(SysCache[cacheId]))
1291 0 : elog(ERROR, "invalid cache ID: %d", cacheId);
1292 73656 : if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
1293 : {
1294 0 : InitCatCachePhase2(SysCache[cacheId], false);
1295 0 : Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
1296 : }
1297 :
1298 73656 : return heap_getattr(tup, attributeNumber,
1299 : SysCache[cacheId]->cc_tupdesc,
1300 : isNull);
1301 : }
1302 :
1303 : /*
1304 : * GetSysCacheHashValue
1305 : *
1306 : * Get the hash value that would be used for a tuple in the specified cache
1307 : * with the given search keys.
1308 : *
1309 : * The reason for exposing this as part of the API is that the hash value is
1310 : * exposed in cache invalidation operations, so there are places outside the
1311 : * catcache code that need to be able to compute the hash values.
1312 : */
1313 : uint32
1314 5945 : GetSysCacheHashValue(int cacheId,
1315 : Datum key1,
1316 : Datum key2,
1317 : Datum key3,
1318 : Datum key4)
1319 : {
1320 11890 : if (cacheId < 0 || cacheId >= SysCacheSize ||
1321 5945 : !PointerIsValid(SysCache[cacheId]))
1322 0 : elog(ERROR, "invalid cache ID: %d", cacheId);
1323 :
1324 5945 : return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
1325 : }
1326 :
1327 : /*
1328 : * List-search interface
1329 : */
1330 : struct catclist *
1331 101667 : SearchSysCacheList(int cacheId, int nkeys,
1332 : Datum key1, Datum key2, Datum key3, Datum key4)
1333 : {
1334 203334 : if (cacheId < 0 || cacheId >= SysCacheSize ||
1335 101667 : !PointerIsValid(SysCache[cacheId]))
1336 0 : elog(ERROR, "invalid cache ID: %d", cacheId);
1337 :
1338 101667 : return SearchCatCacheList(SysCache[cacheId], nkeys,
1339 : key1, key2, key3, key4);
1340 : }
1341 :
1342 : /*
1343 : * SysCacheInvalidate
1344 : *
1345 : * Invalidate entries in the specified cache, given a hash value.
1346 : * See CatCacheInvalidate() for more info.
1347 : *
1348 : * This routine is only quasi-public: it should only be used by inval.c.
1349 : */
1350 : void
1351 692184 : SysCacheInvalidate(int cacheId, uint32 hashValue)
1352 : {
1353 692184 : if (cacheId < 0 || cacheId >= SysCacheSize)
1354 0 : elog(ERROR, "invalid cache ID: %d", cacheId);
1355 :
1356 : /* if this cache isn't initialized yet, no need to do anything */
1357 692184 : if (!PointerIsValid(SysCache[cacheId]))
1358 692184 : return;
1359 :
1360 692184 : CatCacheInvalidate(SysCache[cacheId], hashValue);
1361 : }
1362 :
1363 : /*
1364 : * Certain relations that do not have system caches send snapshot invalidation
1365 : * messages in lieu of catcache messages. This is for the benefit of
1366 : * GetCatalogSnapshot(), which can then reuse its existing MVCC snapshot
1367 : * for scanning one of those catalogs, rather than taking a new one, if no
1368 : * invalidation has been received.
1369 : *
1370 : * Relations that have syscaches need not (and must not) be listed here. The
1371 : * catcache invalidation messages will also flush the snapshot. If you add a
1372 : * syscache for one of these relations, remove it from this list.
1373 : */
1374 : bool
1375 462599 : RelationInvalidatesSnapshotsOnly(Oid relid)
1376 : {
1377 462599 : switch (relid)
1378 : {
1379 : case DbRoleSettingRelationId:
1380 : case DependRelationId:
1381 : case SharedDependRelationId:
1382 : case DescriptionRelationId:
1383 : case SharedDescriptionRelationId:
1384 : case SecLabelRelationId:
1385 : case SharedSecLabelRelationId:
1386 165421 : return true;
1387 : default:
1388 297178 : break;
1389 : }
1390 :
1391 297178 : return false;
1392 : }
1393 :
1394 : /*
1395 : * Test whether a relation has a system cache.
1396 : */
1397 : bool
1398 189436 : RelationHasSysCache(Oid relid)
1399 : {
1400 189436 : int low = 0,
1401 189436 : high = SysCacheRelationOidSize - 1;
1402 :
1403 1186745 : while (low <= high)
1404 : {
1405 980574 : int middle = low + (high - low) / 2;
1406 :
1407 980574 : if (SysCacheRelationOid[middle] == relid)
1408 172701 : return true;
1409 807873 : if (SysCacheRelationOid[middle] < relid)
1410 339461 : low = middle + 1;
1411 : else
1412 468412 : high = middle - 1;
1413 : }
1414 :
1415 16735 : return false;
1416 : }
1417 :
1418 : /*
1419 : * Test whether a relation supports a system cache, ie it is either a
1420 : * cached table or the index used for a cache.
1421 : */
1422 : bool
1423 64465 : RelationSupportsSysCache(Oid relid)
1424 : {
1425 64465 : int low = 0,
1426 64465 : high = SysCacheSupportingRelOidSize - 1;
1427 :
1428 577823 : while (low <= high)
1429 : {
1430 450081 : int middle = low + (high - low) / 2;
1431 :
1432 450081 : if (SysCacheSupportingRelOid[middle] == relid)
1433 1188 : return true;
1434 448893 : if (SysCacheSupportingRelOid[middle] < relid)
1435 445566 : low = middle + 1;
1436 : else
1437 3327 : high = middle - 1;
1438 : }
1439 :
1440 63277 : return false;
1441 : }
1442 :
1443 :
1444 : /*
1445 : * OID comparator for pg_qsort
1446 : */
1447 : static int
1448 544856 : oid_compare(const void *a, const void *b)
1449 : {
1450 544856 : Oid oa = *((const Oid *) a);
1451 544856 : Oid ob = *((const Oid *) b);
1452 :
1453 544856 : if (oa == ob)
1454 28392 : return 0;
1455 516464 : return (oa > ob) ? 1 : -1;
1456 : }
|