]> granicus.if.org Git - postgresql/blob - src/backend/utils/cache/syscache.c
Implement multivariate n-distinct coefficients
[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_staname,
735                         Anum_pg_statistic_ext_stanamespace,
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 #define SysCacheSize    ((int) lengthof(cacheinfo))
975
976 static CatCache *SysCache[SysCacheSize];
977
978 static bool CacheInitialized = false;
979
980 /* Sorted array of OIDs of tables that have caches on them */
981 static Oid      SysCacheRelationOid[SysCacheSize];
982 static int      SysCacheRelationOidSize;
983
984 /* Sorted array of OIDs of tables and indexes used by caches */
985 static Oid      SysCacheSupportingRelOid[SysCacheSize * 2];
986 static int      SysCacheSupportingRelOidSize;
987
988 static int      oid_compare(const void *a, const void *b);
989
990
991 /*
992  * InitCatalogCache - initialize the caches
993  *
994  * Note that no database access is done here; we only allocate memory
995  * and initialize the cache structure.  Interrogation of the database
996  * to complete initialization of a cache happens upon first use
997  * of that cache.
998  */
999 void
1000 InitCatalogCache(void)
1001 {
1002         int                     cacheId;
1003         int                     i,
1004                                 j;
1005
1006         Assert(!CacheInitialized);
1007
1008         SysCacheRelationOidSize = SysCacheSupportingRelOidSize = 0;
1009
1010         for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
1011         {
1012                 SysCache[cacheId] = InitCatCache(cacheId,
1013                                                                                  cacheinfo[cacheId].reloid,
1014                                                                                  cacheinfo[cacheId].indoid,
1015                                                                                  cacheinfo[cacheId].nkeys,
1016                                                                                  cacheinfo[cacheId].key,
1017                                                                                  cacheinfo[cacheId].nbuckets);
1018                 if (!PointerIsValid(SysCache[cacheId]))
1019                         elog(ERROR, "could not initialize cache %u (%d)",
1020                                  cacheinfo[cacheId].reloid, cacheId);
1021                 /* Accumulate data for OID lists, too */
1022                 SysCacheRelationOid[SysCacheRelationOidSize++] =
1023                         cacheinfo[cacheId].reloid;
1024                 SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
1025                         cacheinfo[cacheId].reloid;
1026                 SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
1027                         cacheinfo[cacheId].indoid;
1028                 /* see comments for RelationInvalidatesSnapshotsOnly */
1029                 Assert(!RelationInvalidatesSnapshotsOnly(cacheinfo[cacheId].reloid));
1030         }
1031
1032         Assert(SysCacheRelationOidSize <= lengthof(SysCacheRelationOid));
1033         Assert(SysCacheSupportingRelOidSize <= lengthof(SysCacheSupportingRelOid));
1034
1035         /* Sort and de-dup OID arrays, so we can use binary search. */
1036         pg_qsort(SysCacheRelationOid, SysCacheRelationOidSize,
1037                          sizeof(Oid), oid_compare);
1038         for (i = 1, j = 0; i < SysCacheRelationOidSize; i++)
1039         {
1040                 if (SysCacheRelationOid[i] != SysCacheRelationOid[j])
1041                         SysCacheRelationOid[++j] = SysCacheRelationOid[i];
1042         }
1043         SysCacheRelationOidSize = j + 1;
1044
1045         pg_qsort(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
1046                          sizeof(Oid), oid_compare);
1047         for (i = 1, j = 0; i < SysCacheSupportingRelOidSize; i++)
1048         {
1049                 if (SysCacheSupportingRelOid[i] != SysCacheSupportingRelOid[j])
1050                         SysCacheSupportingRelOid[++j] = SysCacheSupportingRelOid[i];
1051         }
1052         SysCacheSupportingRelOidSize = j + 1;
1053
1054         CacheInitialized = true;
1055 }
1056
1057 /*
1058  * InitCatalogCachePhase2 - finish initializing the caches
1059  *
1060  * Finish initializing all the caches, including necessary database
1061  * access.
1062  *
1063  * This is *not* essential; normally we allow syscaches to be initialized
1064  * on first use.  However, it is useful as a mechanism to preload the
1065  * relcache with entries for the most-commonly-used system catalogs.
1066  * Therefore, we invoke this routine when we need to write a new relcache
1067  * init file.
1068  */
1069 void
1070 InitCatalogCachePhase2(void)
1071 {
1072         int                     cacheId;
1073
1074         Assert(CacheInitialized);
1075
1076         for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
1077                 InitCatCachePhase2(SysCache[cacheId], true);
1078 }
1079
1080
1081 /*
1082  * SearchSysCache
1083  *
1084  *      A layer on top of SearchCatCache that does the initialization and
1085  *      key-setting for you.
1086  *
1087  *      Returns the cache copy of the tuple if one is found, NULL if not.
1088  *      The tuple is the 'cache' copy and must NOT be modified!
1089  *
1090  *      When the caller is done using the tuple, call ReleaseSysCache()
1091  *      to release the reference count grabbed by SearchSysCache().  If this
1092  *      is not done, the tuple will remain locked in cache until end of
1093  *      transaction, which is tolerable but not desirable.
1094  *
1095  *      CAUTION: The tuple that is returned must NOT be freed by the caller!
1096  */
1097 HeapTuple
1098 SearchSysCache(int cacheId,
1099                            Datum key1,
1100                            Datum key2,
1101                            Datum key3,
1102                            Datum key4)
1103 {
1104         if (cacheId < 0 || cacheId >= SysCacheSize ||
1105                 !PointerIsValid(SysCache[cacheId]))
1106                 elog(ERROR, "invalid cache ID: %d", cacheId);
1107
1108         return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
1109 }
1110
1111 /*
1112  * ReleaseSysCache
1113  *              Release previously grabbed reference count on a tuple
1114  */
1115 void
1116 ReleaseSysCache(HeapTuple tuple)
1117 {
1118         ReleaseCatCache(tuple);
1119 }
1120
1121 /*
1122  * SearchSysCacheCopy
1123  *
1124  * A convenience routine that does SearchSysCache and (if successful)
1125  * returns a modifiable copy of the syscache entry.  The original
1126  * syscache entry is released before returning.  The caller should
1127  * heap_freetuple() the result when done with it.
1128  */
1129 HeapTuple
1130 SearchSysCacheCopy(int cacheId,
1131                                    Datum key1,
1132                                    Datum key2,
1133                                    Datum key3,
1134                                    Datum key4)
1135 {
1136         HeapTuple       tuple,
1137                                 newtuple;
1138
1139         tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1140         if (!HeapTupleIsValid(tuple))
1141                 return tuple;
1142         newtuple = heap_copytuple(tuple);
1143         ReleaseSysCache(tuple);
1144         return newtuple;
1145 }
1146
1147 /*
1148  * SearchSysCacheExists
1149  *
1150  * A convenience routine that just probes to see if a tuple can be found.
1151  * No lock is retained on the syscache entry.
1152  */
1153 bool
1154 SearchSysCacheExists(int cacheId,
1155                                          Datum key1,
1156                                          Datum key2,
1157                                          Datum key3,
1158                                          Datum key4)
1159 {
1160         HeapTuple       tuple;
1161
1162         tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1163         if (!HeapTupleIsValid(tuple))
1164                 return false;
1165         ReleaseSysCache(tuple);
1166         return true;
1167 }
1168
1169 /*
1170  * GetSysCacheOid
1171  *
1172  * A convenience routine that does SearchSysCache and returns the OID
1173  * of the found tuple, or InvalidOid if no tuple could be found.
1174  * No lock is retained on the syscache entry.
1175  */
1176 Oid
1177 GetSysCacheOid(int cacheId,
1178                            Datum key1,
1179                            Datum key2,
1180                            Datum key3,
1181                            Datum key4)
1182 {
1183         HeapTuple       tuple;
1184         Oid                     result;
1185
1186         tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
1187         if (!HeapTupleIsValid(tuple))
1188                 return InvalidOid;
1189         result = HeapTupleGetOid(tuple);
1190         ReleaseSysCache(tuple);
1191         return result;
1192 }
1193
1194
1195 /*
1196  * SearchSysCacheAttName
1197  *
1198  * This routine is equivalent to SearchSysCache on the ATTNAME cache,
1199  * except that it will return NULL if the found attribute is marked
1200  * attisdropped.  This is convenient for callers that want to act as
1201  * though dropped attributes don't exist.
1202  */
1203 HeapTuple
1204 SearchSysCacheAttName(Oid relid, const char *attname)
1205 {
1206         HeapTuple       tuple;
1207
1208         tuple = SearchSysCache2(ATTNAME,
1209                                                         ObjectIdGetDatum(relid),
1210                                                         CStringGetDatum(attname));
1211         if (!HeapTupleIsValid(tuple))
1212                 return NULL;
1213         if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
1214         {
1215                 ReleaseSysCache(tuple);
1216                 return NULL;
1217         }
1218         return tuple;
1219 }
1220
1221 /*
1222  * SearchSysCacheCopyAttName
1223  *
1224  * As above, an attisdropped-aware version of SearchSysCacheCopy.
1225  */
1226 HeapTuple
1227 SearchSysCacheCopyAttName(Oid relid, const char *attname)
1228 {
1229         HeapTuple       tuple,
1230                                 newtuple;
1231
1232         tuple = SearchSysCacheAttName(relid, attname);
1233         if (!HeapTupleIsValid(tuple))
1234                 return tuple;
1235         newtuple = heap_copytuple(tuple);
1236         ReleaseSysCache(tuple);
1237         return newtuple;
1238 }
1239
1240 /*
1241  * SearchSysCacheExistsAttName
1242  *
1243  * As above, an attisdropped-aware version of SearchSysCacheExists.
1244  */
1245 bool
1246 SearchSysCacheExistsAttName(Oid relid, const char *attname)
1247 {
1248         HeapTuple       tuple;
1249
1250         tuple = SearchSysCacheAttName(relid, attname);
1251         if (!HeapTupleIsValid(tuple))
1252                 return false;
1253         ReleaseSysCache(tuple);
1254         return true;
1255 }
1256
1257
1258 /*
1259  * SysCacheGetAttr
1260  *
1261  *              Given a tuple previously fetched by SearchSysCache(),
1262  *              extract a specific attribute.
1263  *
1264  * This is equivalent to using heap_getattr() on a tuple fetched
1265  * from a non-cached relation.  Usually, this is only used for attributes
1266  * that could be NULL or variable length; the fixed-size attributes in
1267  * a system table are accessed just by mapping the tuple onto the C struct
1268  * declarations from include/catalog/.
1269  *
1270  * As with heap_getattr(), if the attribute is of a pass-by-reference type
1271  * then a pointer into the tuple data area is returned --- the caller must
1272  * not modify or pfree the datum!
1273  *
1274  * Note: it is legal to use SysCacheGetAttr() with a cacheId referencing
1275  * a different cache for the same catalog the tuple was fetched from.
1276  */
1277 Datum
1278 SysCacheGetAttr(int cacheId, HeapTuple tup,
1279                                 AttrNumber attributeNumber,
1280                                 bool *isNull)
1281 {
1282         /*
1283          * We just need to get the TupleDesc out of the cache entry, and then we
1284          * can apply heap_getattr().  Normally the cache control data is already
1285          * valid (because the caller recently fetched the tuple via this same
1286          * cache), but there are cases where we have to initialize the cache here.
1287          */
1288         if (cacheId < 0 || cacheId >= SysCacheSize ||
1289                 !PointerIsValid(SysCache[cacheId]))
1290                 elog(ERROR, "invalid cache ID: %d", cacheId);
1291         if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
1292         {
1293                 InitCatCachePhase2(SysCache[cacheId], false);
1294                 Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
1295         }
1296
1297         return heap_getattr(tup, attributeNumber,
1298                                                 SysCache[cacheId]->cc_tupdesc,
1299                                                 isNull);
1300 }
1301
1302 /*
1303  * GetSysCacheHashValue
1304  *
1305  * Get the hash value that would be used for a tuple in the specified cache
1306  * with the given search keys.
1307  *
1308  * The reason for exposing this as part of the API is that the hash value is
1309  * exposed in cache invalidation operations, so there are places outside the
1310  * catcache code that need to be able to compute the hash values.
1311  */
1312 uint32
1313 GetSysCacheHashValue(int cacheId,
1314                                          Datum key1,
1315                                          Datum key2,
1316                                          Datum key3,
1317                                          Datum key4)
1318 {
1319         if (cacheId < 0 || cacheId >= SysCacheSize ||
1320                 !PointerIsValid(SysCache[cacheId]))
1321                 elog(ERROR, "invalid cache ID: %d", cacheId);
1322
1323         return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
1324 }
1325
1326 /*
1327  * List-search interface
1328  */
1329 struct catclist *
1330 SearchSysCacheList(int cacheId, int nkeys,
1331                                    Datum key1, Datum key2, Datum key3, Datum key4)
1332 {
1333         if (cacheId < 0 || cacheId >= SysCacheSize ||
1334                 !PointerIsValid(SysCache[cacheId]))
1335                 elog(ERROR, "invalid cache ID: %d", cacheId);
1336
1337         return SearchCatCacheList(SysCache[cacheId], nkeys,
1338                                                           key1, key2, key3, key4);
1339 }
1340
1341 /*
1342  * Certain relations that do not have system caches send snapshot invalidation
1343  * messages in lieu of catcache messages.  This is for the benefit of
1344  * GetCatalogSnapshot(), which can then reuse its existing MVCC snapshot
1345  * for scanning one of those catalogs, rather than taking a new one, if no
1346  * invalidation has been received.
1347  *
1348  * Relations that have syscaches need not (and must not) be listed here.  The
1349  * catcache invalidation messages will also flush the snapshot.  If you add a
1350  * syscache for one of these relations, remove it from this list.
1351  */
1352 bool
1353 RelationInvalidatesSnapshotsOnly(Oid relid)
1354 {
1355         switch (relid)
1356         {
1357                 case DbRoleSettingRelationId:
1358                 case DependRelationId:
1359                 case SharedDependRelationId:
1360                 case DescriptionRelationId:
1361                 case SharedDescriptionRelationId:
1362                 case SecLabelRelationId:
1363                 case SharedSecLabelRelationId:
1364                         return true;
1365                 default:
1366                         break;
1367         }
1368
1369         return false;
1370 }
1371
1372 /*
1373  * Test whether a relation has a system cache.
1374  */
1375 bool
1376 RelationHasSysCache(Oid relid)
1377 {
1378         int                     low = 0,
1379                                 high = SysCacheRelationOidSize - 1;
1380
1381         while (low <= high)
1382         {
1383                 int                     middle = low + (high - low) / 2;
1384
1385                 if (SysCacheRelationOid[middle] == relid)
1386                         return true;
1387                 if (SysCacheRelationOid[middle] < relid)
1388                         low = middle + 1;
1389                 else
1390                         high = middle - 1;
1391         }
1392
1393         return false;
1394 }
1395
1396 /*
1397  * Test whether a relation supports a system cache, ie it is either a
1398  * cached table or the index used for a cache.
1399  */
1400 bool
1401 RelationSupportsSysCache(Oid relid)
1402 {
1403         int                     low = 0,
1404                                 high = SysCacheSupportingRelOidSize - 1;
1405
1406         while (low <= high)
1407         {
1408                 int                     middle = low + (high - low) / 2;
1409
1410                 if (SysCacheSupportingRelOid[middle] == relid)
1411                         return true;
1412                 if (SysCacheSupportingRelOid[middle] < relid)
1413                         low = middle + 1;
1414                 else
1415                         high = middle - 1;
1416         }
1417
1418         return false;
1419 }
1420
1421
1422 /*
1423  * OID comparator for pg_qsort
1424  */
1425 static int
1426 oid_compare(const void *a, const void *b)
1427 {
1428         Oid                     oa = *((const Oid *) a);
1429         Oid                     ob = *((const Oid *) b);
1430
1431         if (oa == ob)
1432                 return 0;
1433         return (oa > ob) ? 1 : -1;
1434 }