]> granicus.if.org Git - postgresql/blob - src/backend/utils/cache/syscache.c
922718c9d17378d4fb230c775a5c7bf1c86e27c4
[postgresql] / src / backend / utils / cache / syscache.c
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         {RangeRelationId,                       /* RANGETYPE */
610                 RangeTypidIndexId,
611                 1,
612                 {
613                         Anum_pg_range_rngtypid,
614                         0,
615                         0,
616                         0
617                 },
618                 4
619         },
620         {RelationRelationId,            /* RELNAMENSP */
621                 ClassNameNspIndexId,
622                 2,
623                 {
624                         Anum_pg_class_relname,
625                         Anum_pg_class_relnamespace,
626                         0,
627                         0
628                 },
629                 128
630         },
631         {RelationRelationId,            /* RELOID */
632                 ClassOidIndexId,
633                 1,
634                 {
635                         ObjectIdAttributeNumber,
636                         0,
637                         0,
638                         0
639                 },
640                 128
641         },
642         {ReplicationOriginRelationId,           /* REPLORIGIDENT */
643                 ReplicationOriginIdentIndex,
644                 1,
645                 {
646                         Anum_pg_replication_origin_roident,
647                         0,
648                         0,
649                         0
650                 },
651                 16
652         },
653         {ReplicationOriginRelationId,           /* REPLORIGNAME */
654                 ReplicationOriginNameIndex,
655                 1,
656                 {
657                         Anum_pg_replication_origin_roname,
658                         0,
659                         0,
660                         0
661                 },
662                 16
663         },
664         {PublicationRelationId,         /* PUBLICATIONOID */
665                 PublicationObjectIndexId,
666                 1,
667                 {
668                         ObjectIdAttributeNumber,
669                         0,
670                         0,
671                         0
672                 },
673                 8
674         },
675         {PublicationRelationId,         /* PUBLICATIONNAME */
676                 PublicationNameIndexId,
677                 1,
678                 {
679                         Anum_pg_publication_pubname,
680                         0,
681                         0,
682                         0
683                 },
684                 8
685         },
686         {PublicationRelRelationId,      /* PUBLICATIONREL */
687                 PublicationRelObjectIndexId,
688                 1,
689                 {
690                         ObjectIdAttributeNumber,
691                         0,
692                         0,
693                         0
694                 },
695                 64
696         },
697         {PublicationRelRelationId,      /* PUBLICATIONRELMAP */
698                 PublicationRelPrrelidPrpubidIndexId,
699                 2,
700                 {
701                         Anum_pg_publication_rel_prrelid,
702                         Anum_pg_publication_rel_prpubid,
703                         0,
704                         0
705                 },
706                 64
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,        /* SUBSCRIPTIONOID */
764                 SubscriptionObjectIndexId,
765                 1,
766                 {
767                         ObjectIdAttributeNumber,
768                         0,
769                         0,
770                         0
771                 },
772                 4
773         },
774         {SubscriptionRelationId,        /* SUBSCRIPTIONNAME */
775                 SubscriptionNameIndexId,
776                 2,
777                 {
778                         Anum_pg_subscription_subdbid,
779                         Anum_pg_subscription_subname,
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 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
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
1099 SearchSysCache(int cacheId,
1100                            Datum key1,
1101                            Datum key2,
1102                            Datum key3,
1103                            Datum key4)
1104 {
1105         if (cacheId < 0 || cacheId >= SysCacheSize ||
1106                 !PointerIsValid(SysCache[cacheId]))
1107                 elog(ERROR, "invalid cache ID: %d", cacheId);
1108
1109         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 ReleaseSysCache(HeapTuple tuple)
1118 {
1119         ReleaseCatCache(tuple);
1120 }
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 SearchSysCacheCopy(int cacheId,
1132                                    Datum key1,
1133                                    Datum key2,
1134                                    Datum key3,
1135                                    Datum key4)
1136 {
1137         HeapTuple       tuple,
1138                                 newtuple;
1139
1140         tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1141         if (!HeapTupleIsValid(tuple))
1142                 return tuple;
1143         newtuple = heap_copytuple(tuple);
1144         ReleaseSysCache(tuple);
1145         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 SearchSysCacheExists(int cacheId,
1156                                          Datum key1,
1157                                          Datum key2,
1158                                          Datum key3,
1159                                          Datum key4)
1160 {
1161         HeapTuple       tuple;
1162
1163         tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1164         if (!HeapTupleIsValid(tuple))
1165                 return false;
1166         ReleaseSysCache(tuple);
1167         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 GetSysCacheOid(int cacheId,
1179                            Datum key1,
1180                            Datum key2,
1181                            Datum key3,
1182                            Datum key4)
1183 {
1184         HeapTuple       tuple;
1185         Oid                     result;
1186
1187         tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1188         if (!HeapTupleIsValid(tuple))
1189                 return InvalidOid;
1190         result = HeapTupleGetOid(tuple);
1191         ReleaseSysCache(tuple);
1192         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 SearchSysCacheAttName(Oid relid, const char *attname)
1206 {
1207         HeapTuple       tuple;
1208
1209         tuple = SearchSysCache2(ATTNAME,
1210                                                         ObjectIdGetDatum(relid),
1211                                                         CStringGetDatum(attname));
1212         if (!HeapTupleIsValid(tuple))
1213                 return NULL;
1214         if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
1215         {
1216                 ReleaseSysCache(tuple);
1217                 return NULL;
1218         }
1219         return tuple;
1220 }
1221
1222 /*
1223  * SearchSysCacheCopyAttName
1224  *
1225  * As above, an attisdropped-aware version of SearchSysCacheCopy.
1226  */
1227 HeapTuple
1228 SearchSysCacheCopyAttName(Oid relid, const char *attname)
1229 {
1230         HeapTuple       tuple,
1231                                 newtuple;
1232
1233         tuple = SearchSysCacheAttName(relid, attname);
1234         if (!HeapTupleIsValid(tuple))
1235                 return tuple;
1236         newtuple = heap_copytuple(tuple);
1237         ReleaseSysCache(tuple);
1238         return newtuple;
1239 }
1240
1241 /*
1242  * SearchSysCacheExistsAttName
1243  *
1244  * As above, an attisdropped-aware version of SearchSysCacheExists.
1245  */
1246 bool
1247 SearchSysCacheExistsAttName(Oid relid, const char *attname)
1248 {
1249         HeapTuple       tuple;
1250
1251         tuple = SearchSysCacheAttName(relid, attname);
1252         if (!HeapTupleIsValid(tuple))
1253                 return false;
1254         ReleaseSysCache(tuple);
1255         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 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         if (cacheId < 0 || cacheId >= SysCacheSize ||
1290                 !PointerIsValid(SysCache[cacheId]))
1291                 elog(ERROR, "invalid cache ID: %d", cacheId);
1292         if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
1293         {
1294                 InitCatCachePhase2(SysCache[cacheId], false);
1295                 Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
1296         }
1297
1298         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 GetSysCacheHashValue(int cacheId,
1315                                          Datum key1,
1316                                          Datum key2,
1317                                          Datum key3,
1318                                          Datum key4)
1319 {
1320         if (cacheId < 0 || cacheId >= SysCacheSize ||
1321                 !PointerIsValid(SysCache[cacheId]))
1322                 elog(ERROR, "invalid cache ID: %d", cacheId);
1323
1324         return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
1325 }
1326
1327 /*
1328  * List-search interface
1329  */
1330 struct catclist *
1331 SearchSysCacheList(int cacheId, int nkeys,
1332                                    Datum key1, Datum key2, Datum key3, Datum key4)
1333 {
1334         if (cacheId < 0 || cacheId >= SysCacheSize ||
1335                 !PointerIsValid(SysCache[cacheId]))
1336                 elog(ERROR, "invalid cache ID: %d", cacheId);
1337
1338         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 SysCacheInvalidate(int cacheId, uint32 hashValue)
1352 {
1353         if (cacheId < 0 || cacheId >= SysCacheSize)
1354                 elog(ERROR, "invalid cache ID: %d", cacheId);
1355
1356         /* if this cache isn't initialized yet, no need to do anything */
1357         if (!PointerIsValid(SysCache[cacheId]))
1358                 return;
1359
1360         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 RelationInvalidatesSnapshotsOnly(Oid relid)
1376 {
1377         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                         return true;
1387                 default:
1388                         break;
1389         }
1390
1391         return false;
1392 }
1393
1394 /*
1395  * Test whether a relation has a system cache.
1396  */
1397 bool
1398 RelationHasSysCache(Oid relid)
1399 {
1400         int                     low = 0,
1401                                 high = SysCacheRelationOidSize - 1;
1402
1403         while (low <= high)
1404         {
1405                 int                     middle = low + (high - low) / 2;
1406
1407                 if (SysCacheRelationOid[middle] == relid)
1408                         return true;
1409                 if (SysCacheRelationOid[middle] < relid)
1410                         low = middle + 1;
1411                 else
1412                         high = middle - 1;
1413         }
1414
1415         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 RelationSupportsSysCache(Oid relid)
1424 {
1425         int                     low = 0,
1426                                 high = SysCacheSupportingRelOidSize - 1;
1427
1428         while (low <= high)
1429         {
1430                 int                     middle = low + (high - low) / 2;
1431
1432                 if (SysCacheSupportingRelOid[middle] == relid)
1433                         return true;
1434                 if (SysCacheSupportingRelOid[middle] < relid)
1435                         low = middle + 1;
1436                 else
1437                         high = middle - 1;
1438         }
1439
1440         return false;
1441 }
1442
1443
1444 /*
1445  * OID comparator for pg_qsort
1446  */
1447 static int
1448 oid_compare(const void *a, const void *b)
1449 {
1450         Oid                     oa = *((const Oid *) a);
1451         Oid                     ob = *((const Oid *) b);
1452
1453         if (oa == ob)
1454                 return 0;
1455         return (oa > ob) ? 1 : -1;
1456 }