Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * syscache.c
4 : * System cache management routines
5 : *
6 : * Portions Copyright (c) 1996-2023, 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/pg_aggregate.h"
26 : #include "catalog/pg_am.h"
27 : #include "catalog/pg_amop.h"
28 : #include "catalog/pg_amproc.h"
29 : #include "catalog/pg_auth_members.h"
30 : #include "catalog/pg_authid.h"
31 : #include "catalog/pg_cast.h"
32 : #include "catalog/pg_collation.h"
33 : #include "catalog/pg_constraint.h"
34 : #include "catalog/pg_conversion.h"
35 : #include "catalog/pg_database.h"
36 : #include "catalog/pg_db_role_setting.h"
37 : #include "catalog/pg_default_acl.h"
38 : #include "catalog/pg_depend.h"
39 : #include "catalog/pg_description.h"
40 : #include "catalog/pg_enum.h"
41 : #include "catalog/pg_event_trigger.h"
42 : #include "catalog/pg_foreign_data_wrapper.h"
43 : #include "catalog/pg_foreign_server.h"
44 : #include "catalog/pg_foreign_table.h"
45 : #include "catalog/pg_language.h"
46 : #include "catalog/pg_namespace.h"
47 : #include "catalog/pg_opclass.h"
48 : #include "catalog/pg_operator.h"
49 : #include "catalog/pg_opfamily.h"
50 : #include "catalog/pg_parameter_acl.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_namespace.h"
55 : #include "catalog/pg_publication_rel.h"
56 : #include "catalog/pg_range.h"
57 : #include "catalog/pg_replication_origin.h"
58 : #include "catalog/pg_rewrite.h"
59 : #include "catalog/pg_seclabel.h"
60 : #include "catalog/pg_sequence.h"
61 : #include "catalog/pg_shdepend.h"
62 : #include "catalog/pg_shdescription.h"
63 : #include "catalog/pg_shseclabel.h"
64 : #include "catalog/pg_statistic.h"
65 : #include "catalog/pg_statistic_ext.h"
66 : #include "catalog/pg_statistic_ext_data.h"
67 : #include "catalog/pg_subscription.h"
68 : #include "catalog/pg_subscription_rel.h"
69 : #include "catalog/pg_tablespace.h"
70 : #include "catalog/pg_transform.h"
71 : #include "catalog/pg_ts_config.h"
72 : #include "catalog/pg_ts_config_map.h"
73 : #include "catalog/pg_ts_dict.h"
74 : #include "catalog/pg_ts_parser.h"
75 : #include "catalog/pg_ts_template.h"
76 : #include "catalog/pg_type.h"
77 : #include "catalog/pg_user_mapping.h"
78 : #include "lib/qunique.h"
79 : #include "utils/catcache.h"
80 : #include "utils/lsyscache.h"
81 : #include "utils/rel.h"
82 : #include "utils/syscache.h"
83 :
84 : /*---------------------------------------------------------------------------
85 :
86 : Adding system caches:
87 :
88 : Add your new cache to the list in include/utils/syscache.h.
89 : Keep the list sorted alphabetically.
90 :
91 : Add your entry to the cacheinfo[] array below. All cache lists are
92 : alphabetical, so add it in the proper place. Specify the relation OID,
93 : index OID, number of keys, key attribute numbers, and initial number of
94 : hash buckets.
95 :
96 : The number of hash buckets must be a power of 2. It's reasonable to
97 : set this to the number of entries that might be in the particular cache
98 : in a medium-size database.
99 :
100 : There must be a unique index underlying each syscache (ie, an index
101 : whose key is the same as that of the cache). If there is not one
102 : already, add the definition for it to include/catalog/pg_*.h using
103 : DECLARE_UNIQUE_INDEX.
104 : (Adding an index requires a catversion.h update, while simply
105 : adding/deleting caches only requires a recompile.)
106 :
107 : Finally, any place your relation gets heap_insert() or
108 : heap_update() calls, use CatalogTupleInsert() or CatalogTupleUpdate()
109 : instead, which also update indexes. The heap_* calls do not do that.
110 :
111 : *---------------------------------------------------------------------------
112 : */
113 :
114 : /*
115 : * struct cachedesc: information defining a single syscache
116 : */
117 : struct cachedesc
118 : {
119 : Oid reloid; /* OID of the relation being cached */
120 : Oid indoid; /* OID of index relation for this cache */
121 : int nkeys; /* # of keys needed for cache lookup */
122 : int key[4]; /* attribute numbers of key attrs */
123 : int nbuckets; /* number of hash buckets for this cache */
124 : };
125 :
126 : /* Macro to provide nkeys and key array with convenient syntax. */
127 : #define KEY(...) VA_ARGS_NARGS(__VA_ARGS__), { __VA_ARGS__ }
128 :
129 : static const struct cachedesc cacheinfo[] = {
130 : [AGGFNOID] = {
131 : AggregateRelationId,
132 : AggregateFnoidIndexId,
133 : KEY(Anum_pg_aggregate_aggfnoid),
134 : 16
135 : },
136 : [AMNAME] = {
137 : AccessMethodRelationId,
138 : AmNameIndexId,
139 : KEY(Anum_pg_am_amname),
140 : 4
141 : },
142 : [AMOID] = {
143 : AccessMethodRelationId,
144 : AmOidIndexId,
145 : KEY(Anum_pg_am_oid),
146 : 4
147 : },
148 : [AMOPOPID] = {
149 : AccessMethodOperatorRelationId,
150 : AccessMethodOperatorIndexId,
151 : KEY(Anum_pg_amop_amopopr,
152 : Anum_pg_amop_amoppurpose,
153 : Anum_pg_amop_amopfamily),
154 : 64
155 : },
156 : [AMOPSTRATEGY] = {
157 : AccessMethodOperatorRelationId,
158 : AccessMethodStrategyIndexId,
159 : KEY(Anum_pg_amop_amopfamily,
160 : Anum_pg_amop_amoplefttype,
161 : Anum_pg_amop_amoprighttype,
162 : Anum_pg_amop_amopstrategy),
163 : 64
164 : },
165 : [AMPROCNUM] = {
166 : AccessMethodProcedureRelationId,
167 : AccessMethodProcedureIndexId,
168 : KEY(Anum_pg_amproc_amprocfamily,
169 : Anum_pg_amproc_amproclefttype,
170 : Anum_pg_amproc_amprocrighttype,
171 : Anum_pg_amproc_amprocnum),
172 : 16
173 : },
174 : [ATTNAME] = {
175 : AttributeRelationId,
176 : AttributeRelidNameIndexId,
177 : KEY(Anum_pg_attribute_attrelid,
178 : Anum_pg_attribute_attname),
179 : 32
180 : },
181 : [ATTNUM] = {
182 : AttributeRelationId,
183 : AttributeRelidNumIndexId,
184 : KEY(Anum_pg_attribute_attrelid,
185 : Anum_pg_attribute_attnum),
186 : 128
187 : },
188 : [AUTHMEMMEMROLE] = {
189 : AuthMemRelationId,
190 : AuthMemMemRoleIndexId,
191 : KEY(Anum_pg_auth_members_member,
192 : Anum_pg_auth_members_roleid,
193 : Anum_pg_auth_members_grantor),
194 : 8
195 : },
196 : [AUTHMEMROLEMEM] = {
197 : AuthMemRelationId,
198 : AuthMemRoleMemIndexId,
199 : KEY(Anum_pg_auth_members_roleid,
200 : Anum_pg_auth_members_member,
201 : Anum_pg_auth_members_grantor),
202 : 8
203 : },
204 : [AUTHNAME] = {
205 : AuthIdRelationId,
206 : AuthIdRolnameIndexId,
207 : KEY(Anum_pg_authid_rolname),
208 : 8
209 : },
210 : [AUTHOID] = {
211 : AuthIdRelationId,
212 : AuthIdOidIndexId,
213 : KEY(Anum_pg_authid_oid),
214 : 8
215 : },
216 : [CASTSOURCETARGET] = {
217 : CastRelationId,
218 : CastSourceTargetIndexId,
219 : KEY(Anum_pg_cast_castsource,
220 : Anum_pg_cast_casttarget),
221 : 256
222 : },
223 : [CLAAMNAMENSP] = {
224 : OperatorClassRelationId,
225 : OpclassAmNameNspIndexId,
226 : KEY(Anum_pg_opclass_opcmethod,
227 : Anum_pg_opclass_opcname,
228 : Anum_pg_opclass_opcnamespace),
229 : 8
230 : },
231 : [CLAOID] = {
232 : OperatorClassRelationId,
233 : OpclassOidIndexId,
234 : KEY(Anum_pg_opclass_oid),
235 : 8
236 : },
237 : [COLLNAMEENCNSP] = {
238 : CollationRelationId,
239 : CollationNameEncNspIndexId,
240 : KEY(Anum_pg_collation_collname,
241 : Anum_pg_collation_collencoding,
242 : Anum_pg_collation_collnamespace),
243 : 8
244 : },
245 : [COLLOID] = {
246 : CollationRelationId,
247 : CollationOidIndexId,
248 : KEY(Anum_pg_collation_oid),
249 : 8
250 : },
251 : [CONDEFAULT] = {
252 : ConversionRelationId,
253 : ConversionDefaultIndexId,
254 : KEY(Anum_pg_conversion_connamespace,
255 : Anum_pg_conversion_conforencoding,
256 : Anum_pg_conversion_contoencoding,
257 : Anum_pg_conversion_oid),
258 : 8
259 : },
260 : [CONNAMENSP] = {
261 : ConversionRelationId,
262 : ConversionNameNspIndexId,
263 : KEY(Anum_pg_conversion_conname,
264 : Anum_pg_conversion_connamespace),
265 : 8
266 : },
267 : [CONSTROID] = {
268 : ConstraintRelationId,
269 : ConstraintOidIndexId,
270 : KEY(Anum_pg_constraint_oid),
271 : 16
272 : },
273 : [CONVOID] = {
274 : ConversionRelationId,
275 : ConversionOidIndexId,
276 : KEY(Anum_pg_conversion_oid),
277 : 8
278 : },
279 : [DATABASEOID] = {
280 : DatabaseRelationId,
281 : DatabaseOidIndexId,
282 : KEY(Anum_pg_database_oid),
283 : 4
284 : },
285 : [DEFACLROLENSPOBJ] = {
286 : DefaultAclRelationId,
287 : DefaultAclRoleNspObjIndexId,
288 : KEY(Anum_pg_default_acl_defaclrole,
289 : Anum_pg_default_acl_defaclnamespace,
290 : Anum_pg_default_acl_defaclobjtype),
291 : 8
292 : },
293 : [ENUMOID] = {
294 : EnumRelationId,
295 : EnumOidIndexId,
296 : KEY(Anum_pg_enum_oid),
297 : 8
298 : },
299 : [ENUMTYPOIDNAME] = {
300 : EnumRelationId,
301 : EnumTypIdLabelIndexId,
302 : KEY(Anum_pg_enum_enumtypid,
303 : Anum_pg_enum_enumlabel),
304 : 8
305 : },
306 : [EVENTTRIGGERNAME] = {
307 : EventTriggerRelationId,
308 : EventTriggerNameIndexId,
309 : KEY(Anum_pg_event_trigger_evtname),
310 : 8
311 : },
312 : [EVENTTRIGGEROID] = {
313 : EventTriggerRelationId,
314 : EventTriggerOidIndexId,
315 : KEY(Anum_pg_event_trigger_oid),
316 : 8
317 : },
318 : [FOREIGNDATAWRAPPERNAME] = {
319 : ForeignDataWrapperRelationId,
320 : ForeignDataWrapperNameIndexId,
321 : KEY(Anum_pg_foreign_data_wrapper_fdwname),
322 : 2
323 : },
324 : [FOREIGNDATAWRAPPEROID] = {
325 : ForeignDataWrapperRelationId,
326 : ForeignDataWrapperOidIndexId,
327 : KEY(Anum_pg_foreign_data_wrapper_oid),
328 : 2
329 : },
330 : [FOREIGNSERVERNAME] = {
331 : ForeignServerRelationId,
332 : ForeignServerNameIndexId,
333 : KEY(Anum_pg_foreign_server_srvname),
334 : 2
335 : },
336 : [FOREIGNSERVEROID] = {
337 : ForeignServerRelationId,
338 : ForeignServerOidIndexId,
339 : KEY(Anum_pg_foreign_server_oid),
340 : 2
341 : },
342 : [FOREIGNTABLEREL] = {
343 : ForeignTableRelationId,
344 : ForeignTableRelidIndexId,
345 : KEY(Anum_pg_foreign_table_ftrelid),
346 : 4
347 : },
348 : [INDEXRELID] = {
349 : IndexRelationId,
350 : IndexRelidIndexId,
351 : KEY(Anum_pg_index_indexrelid),
352 : 64
353 : },
354 : [LANGNAME] = {
355 : LanguageRelationId,
356 : LanguageNameIndexId,
357 : KEY(Anum_pg_language_lanname),
358 : 4
359 : },
360 : [LANGOID] = {
361 : LanguageRelationId,
362 : LanguageOidIndexId,
363 : KEY(Anum_pg_language_oid),
364 : 4
365 : },
366 : [NAMESPACENAME] = {
367 : NamespaceRelationId,
368 : NamespaceNameIndexId,
369 : KEY(Anum_pg_namespace_nspname),
370 : 4
371 : },
372 : [NAMESPACEOID] = {
373 : NamespaceRelationId,
374 : NamespaceOidIndexId,
375 : KEY(Anum_pg_namespace_oid),
376 : 16
377 : },
378 : [OPERNAMENSP] = {
379 : OperatorRelationId,
380 : OperatorNameNspIndexId,
381 : KEY(Anum_pg_operator_oprname,
382 : Anum_pg_operator_oprleft,
383 : Anum_pg_operator_oprright,
384 : Anum_pg_operator_oprnamespace),
385 : 256
386 : },
387 : [OPEROID] = {
388 : OperatorRelationId,
389 : OperatorOidIndexId,
390 : KEY(Anum_pg_operator_oid),
391 : 32
392 : },
393 : [OPFAMILYAMNAMENSP] = {
394 : OperatorFamilyRelationId,
395 : OpfamilyAmNameNspIndexId,
396 : KEY(Anum_pg_opfamily_opfmethod,
397 : Anum_pg_opfamily_opfname,
398 : Anum_pg_opfamily_opfnamespace),
399 : 8
400 : },
401 : [OPFAMILYOID] = {
402 : OperatorFamilyRelationId,
403 : OpfamilyOidIndexId,
404 : KEY(Anum_pg_opfamily_oid),
405 : 8
406 : },
407 : [PARAMETERACLNAME] = {
408 : ParameterAclRelationId,
409 : ParameterAclParnameIndexId,
410 : KEY(Anum_pg_parameter_acl_parname),
411 : 4
412 : },
413 : [PARAMETERACLOID] = {
414 : ParameterAclRelationId,
415 : ParameterAclOidIndexId,
416 : KEY(Anum_pg_parameter_acl_oid),
417 : 4
418 : },
419 : [PARTRELID] = {
420 : PartitionedRelationId,
421 : PartitionedRelidIndexId,
422 : KEY(Anum_pg_partitioned_table_partrelid),
423 : 32
424 : },
425 : [PROCNAMEARGSNSP] = {
426 : ProcedureRelationId,
427 : ProcedureNameArgsNspIndexId,
428 : KEY(Anum_pg_proc_proname,
429 : Anum_pg_proc_proargtypes,
430 : Anum_pg_proc_pronamespace),
431 : 128
432 : },
433 : [PROCOID] = {
434 : ProcedureRelationId,
435 : ProcedureOidIndexId,
436 : KEY(Anum_pg_proc_oid),
437 : 128
438 : },
439 : [PUBLICATIONNAME] = {
440 : PublicationRelationId,
441 : PublicationNameIndexId,
442 : KEY(Anum_pg_publication_pubname),
443 : 8
444 : },
445 : [PUBLICATIONNAMESPACE] = {
446 : PublicationNamespaceRelationId,
447 : PublicationNamespaceObjectIndexId,
448 : KEY(Anum_pg_publication_namespace_oid),
449 : 64
450 : },
451 : [PUBLICATIONNAMESPACEMAP] = {
452 : PublicationNamespaceRelationId,
453 : PublicationNamespacePnnspidPnpubidIndexId,
454 : KEY(Anum_pg_publication_namespace_pnnspid,
455 : Anum_pg_publication_namespace_pnpubid),
456 : 64
457 : },
458 : [PUBLICATIONOID] = {
459 : PublicationRelationId,
460 : PublicationObjectIndexId,
461 : KEY(Anum_pg_publication_oid),
462 : 8
463 : },
464 : [PUBLICATIONREL] = {
465 : PublicationRelRelationId,
466 : PublicationRelObjectIndexId,
467 : KEY(Anum_pg_publication_rel_oid),
468 : 64
469 : },
470 : [PUBLICATIONRELMAP] = {
471 : PublicationRelRelationId,
472 : PublicationRelPrrelidPrpubidIndexId,
473 : KEY(Anum_pg_publication_rel_prrelid,
474 : Anum_pg_publication_rel_prpubid),
475 : 64
476 : },
477 : [RANGEMULTIRANGE] = {
478 : RangeRelationId,
479 : RangeMultirangeTypidIndexId,
480 : KEY(Anum_pg_range_rngmultitypid),
481 : 4
482 : },
483 : [RANGETYPE] = {
484 : RangeRelationId,
485 : RangeTypidIndexId,
486 : KEY(Anum_pg_range_rngtypid),
487 : 4
488 : },
489 : [RELNAMENSP] = {
490 : RelationRelationId,
491 : ClassNameNspIndexId,
492 : KEY(Anum_pg_class_relname,
493 : Anum_pg_class_relnamespace),
494 : 128
495 : },
496 : [RELOID] = {
497 : RelationRelationId,
498 : ClassOidIndexId,
499 : KEY(Anum_pg_class_oid),
500 : 128
501 : },
502 : [REPLORIGIDENT] = {
503 : ReplicationOriginRelationId,
504 : ReplicationOriginIdentIndex,
505 : KEY(Anum_pg_replication_origin_roident),
506 : 16
507 : },
508 : [REPLORIGNAME] = {
509 : ReplicationOriginRelationId,
510 : ReplicationOriginNameIndex,
511 : KEY(Anum_pg_replication_origin_roname),
512 : 16
513 : },
514 : [RULERELNAME] = {
515 : RewriteRelationId,
516 : RewriteRelRulenameIndexId,
517 : KEY(Anum_pg_rewrite_ev_class,
518 : Anum_pg_rewrite_rulename),
519 : 8
520 : },
521 : [SEQRELID] = {
522 : SequenceRelationId,
523 : SequenceRelidIndexId,
524 : KEY(Anum_pg_sequence_seqrelid),
525 : 32
526 : },
527 : [STATEXTDATASTXOID] = {
528 : StatisticExtDataRelationId,
529 : StatisticExtDataStxoidInhIndexId,
530 : KEY(Anum_pg_statistic_ext_data_stxoid,
531 : Anum_pg_statistic_ext_data_stxdinherit),
532 : 4
533 : },
534 : [STATEXTNAMENSP] = {
535 : StatisticExtRelationId,
536 : StatisticExtNameIndexId,
537 : KEY(Anum_pg_statistic_ext_stxname,
538 : Anum_pg_statistic_ext_stxnamespace),
539 : 4
540 : },
541 : [STATEXTOID] = {
542 : StatisticExtRelationId,
543 : StatisticExtOidIndexId,
544 : KEY(Anum_pg_statistic_ext_oid),
545 : 4
546 : },
547 : [STATRELATTINH] = {
548 : StatisticRelationId,
549 : StatisticRelidAttnumInhIndexId,
550 : KEY(Anum_pg_statistic_starelid,
551 : Anum_pg_statistic_staattnum,
552 : Anum_pg_statistic_stainherit),
553 : 128
554 : },
555 : [SUBSCRIPTIONNAME] = {
556 : SubscriptionRelationId,
557 : SubscriptionNameIndexId,
558 : KEY(Anum_pg_subscription_subdbid,
559 : Anum_pg_subscription_subname),
560 : 4
561 : },
562 : [SUBSCRIPTIONOID] = {
563 : SubscriptionRelationId,
564 : SubscriptionObjectIndexId,
565 : KEY(Anum_pg_subscription_oid),
566 : 4
567 : },
568 : [SUBSCRIPTIONRELMAP] = {
569 : SubscriptionRelRelationId,
570 : SubscriptionRelSrrelidSrsubidIndexId,
571 : KEY(Anum_pg_subscription_rel_srrelid,
572 : Anum_pg_subscription_rel_srsubid),
573 : 64
574 : },
575 : [TABLESPACEOID] = {
576 : TableSpaceRelationId,
577 : TablespaceOidIndexId,
578 : KEY(Anum_pg_tablespace_oid),
579 : 4
580 : },
581 : [TRFOID] = {
582 : TransformRelationId,
583 : TransformOidIndexId,
584 : KEY(Anum_pg_transform_oid),
585 : 16
586 : },
587 : [TRFTYPELANG] = {
588 : TransformRelationId,
589 : TransformTypeLangIndexId,
590 : KEY(Anum_pg_transform_trftype,
591 : Anum_pg_transform_trflang),
592 : 16
593 : },
594 : [TSCONFIGMAP] = {
595 : TSConfigMapRelationId,
596 : TSConfigMapIndexId,
597 : KEY(Anum_pg_ts_config_map_mapcfg,
598 : Anum_pg_ts_config_map_maptokentype,
599 : Anum_pg_ts_config_map_mapseqno),
600 : 2
601 : },
602 : [TSCONFIGNAMENSP] = {
603 : TSConfigRelationId,
604 : TSConfigNameNspIndexId,
605 : KEY(Anum_pg_ts_config_cfgname,
606 : Anum_pg_ts_config_cfgnamespace),
607 : 2
608 : },
609 : [TSCONFIGOID] = {
610 : TSConfigRelationId,
611 : TSConfigOidIndexId,
612 : KEY(Anum_pg_ts_config_oid),
613 : 2
614 : },
615 : [TSDICTNAMENSP] = {
616 : TSDictionaryRelationId,
617 : TSDictionaryNameNspIndexId,
618 : KEY(Anum_pg_ts_dict_dictname,
619 : Anum_pg_ts_dict_dictnamespace),
620 : 2
621 : },
622 : [TSDICTOID] = {
623 : TSDictionaryRelationId,
624 : TSDictionaryOidIndexId,
625 : KEY(Anum_pg_ts_dict_oid),
626 : 2
627 : },
628 : [TSPARSERNAMENSP] = {
629 : TSParserRelationId,
630 : TSParserNameNspIndexId,
631 : KEY(Anum_pg_ts_parser_prsname,
632 : Anum_pg_ts_parser_prsnamespace),
633 : 2
634 : },
635 : [TSPARSEROID] = {
636 : TSParserRelationId,
637 : TSParserOidIndexId,
638 : KEY(Anum_pg_ts_parser_oid),
639 : 2
640 : },
641 : [TSTEMPLATENAMENSP] = {
642 : TSTemplateRelationId,
643 : TSTemplateNameNspIndexId,
644 : KEY(Anum_pg_ts_template_tmplname,
645 : Anum_pg_ts_template_tmplnamespace),
646 : 2
647 : },
648 : [TSTEMPLATEOID] = {
649 : TSTemplateRelationId,
650 : TSTemplateOidIndexId,
651 : KEY(Anum_pg_ts_template_oid),
652 : 2
653 : },
654 : [TYPENAMENSP] = {
655 : TypeRelationId,
656 : TypeNameNspIndexId,
657 : KEY(Anum_pg_type_typname,
658 : Anum_pg_type_typnamespace),
659 : 64
660 : },
661 : [TYPEOID] = {
662 : TypeRelationId,
663 : TypeOidIndexId,
664 : KEY(Anum_pg_type_oid),
665 : 64
666 : },
667 : [USERMAPPINGOID] = {
668 : UserMappingRelationId,
669 : UserMappingOidIndexId,
670 : KEY(Anum_pg_user_mapping_oid),
671 : 2
672 : },
673 : [USERMAPPINGUSERSERVER] = {
674 : UserMappingRelationId,
675 : UserMappingUserServerIndexId,
676 : KEY(Anum_pg_user_mapping_umuser,
677 : Anum_pg_user_mapping_umserver),
678 : 2
679 : }
680 : };
681 :
682 : StaticAssertDecl(lengthof(cacheinfo) == SysCacheSize,
683 : "SysCacheSize does not match syscache.c's array");
684 :
685 : static CatCache *SysCache[SysCacheSize];
686 :
687 : static bool CacheInitialized = false;
688 :
689 : /* Sorted array of OIDs of tables that have caches on them */
690 : static Oid SysCacheRelationOid[SysCacheSize];
691 : static int SysCacheRelationOidSize;
692 :
693 : /* Sorted array of OIDs of tables and indexes used by caches */
694 : static Oid SysCacheSupportingRelOid[SysCacheSize * 2];
695 : static int SysCacheSupportingRelOidSize;
696 :
697 : static int oid_compare(const void *a, const void *b);
698 :
699 :
700 : /*
701 : * InitCatalogCache - initialize the caches
702 : *
703 : * Note that no database access is done here; we only allocate memory
704 : * and initialize the cache structure. Interrogation of the database
705 : * to complete initialization of a cache happens upon first use
706 : * of that cache.
707 : */
708 : void
709 24036 : InitCatalogCache(void)
710 : {
711 : int cacheId;
712 :
713 : Assert(!CacheInitialized);
714 :
715 24036 : SysCacheRelationOidSize = SysCacheSupportingRelOidSize = 0;
716 :
717 2019024 : for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
718 : {
719 : /*
720 : * Assert that every enumeration value defined in syscache.h has been
721 : * populated in the cacheinfo array.
722 : */
723 : Assert(cacheinfo[cacheId].reloid != 0);
724 :
725 3989976 : SysCache[cacheId] = InitCatCache(cacheId,
726 : cacheinfo[cacheId].reloid,
727 : cacheinfo[cacheId].indoid,
728 : cacheinfo[cacheId].nkeys,
729 1994988 : cacheinfo[cacheId].key,
730 : cacheinfo[cacheId].nbuckets);
731 1994988 : if (!PointerIsValid(SysCache[cacheId]))
732 0 : elog(ERROR, "could not initialize cache %u (%d)",
733 : cacheinfo[cacheId].reloid, cacheId);
734 : /* Accumulate data for OID lists, too */
735 1994988 : SysCacheRelationOid[SysCacheRelationOidSize++] =
736 1994988 : cacheinfo[cacheId].reloid;
737 1994988 : SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
738 1994988 : cacheinfo[cacheId].reloid;
739 1994988 : SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
740 1994988 : cacheinfo[cacheId].indoid;
741 : /* see comments for RelationInvalidatesSnapshotsOnly */
742 : Assert(!RelationInvalidatesSnapshotsOnly(cacheinfo[cacheId].reloid));
743 : }
744 :
745 : Assert(SysCacheRelationOidSize <= lengthof(SysCacheRelationOid));
746 : Assert(SysCacheSupportingRelOidSize <= lengthof(SysCacheSupportingRelOid));
747 :
748 : /* Sort and de-dup OID arrays, so we can use binary search. */
749 24036 : pg_qsort(SysCacheRelationOid, SysCacheRelationOidSize,
750 : sizeof(Oid), oid_compare);
751 24036 : SysCacheRelationOidSize =
752 24036 : qunique(SysCacheRelationOid, SysCacheRelationOidSize, sizeof(Oid),
753 : oid_compare);
754 :
755 24036 : pg_qsort(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
756 : sizeof(Oid), oid_compare);
757 24036 : SysCacheSupportingRelOidSize =
758 24036 : qunique(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
759 : sizeof(Oid), oid_compare);
760 :
761 24036 : CacheInitialized = true;
762 24036 : }
763 :
764 : /*
765 : * InitCatalogCachePhase2 - finish initializing the caches
766 : *
767 : * Finish initializing all the caches, including necessary database
768 : * access.
769 : *
770 : * This is *not* essential; normally we allow syscaches to be initialized
771 : * on first use. However, it is useful as a mechanism to preload the
772 : * relcache with entries for the most-commonly-used system catalogs.
773 : * Therefore, we invoke this routine when we need to write a new relcache
774 : * init file.
775 : */
776 : void
777 2296 : InitCatalogCachePhase2(void)
778 : {
779 : int cacheId;
780 :
781 : Assert(CacheInitialized);
782 :
783 192826 : for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
784 190532 : InitCatCachePhase2(SysCache[cacheId], true);
785 2294 : }
786 :
787 :
788 : /*
789 : * SearchSysCache
790 : *
791 : * A layer on top of SearchCatCache that does the initialization and
792 : * key-setting for you.
793 : *
794 : * Returns the cache copy of the tuple if one is found, NULL if not.
795 : * The tuple is the 'cache' copy and must NOT be modified!
796 : *
797 : * When the caller is done using the tuple, call ReleaseSysCache()
798 : * to release the reference count grabbed by SearchSysCache(). If this
799 : * is not done, the tuple will remain locked in cache until end of
800 : * transaction, which is tolerable but not desirable.
801 : *
802 : * CAUTION: The tuple that is returned must NOT be freed by the caller!
803 : */
804 : HeapTuple
805 8792244 : SearchSysCache(int cacheId,
806 : Datum key1,
807 : Datum key2,
808 : Datum key3,
809 : Datum key4)
810 : {
811 : Assert(cacheId >= 0 && cacheId < SysCacheSize &&
812 : PointerIsValid(SysCache[cacheId]));
813 :
814 8792244 : return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
815 : }
816 :
817 : HeapTuple
818 80298590 : SearchSysCache1(int cacheId,
819 : Datum key1)
820 : {
821 : Assert(cacheId >= 0 && cacheId < SysCacheSize &&
822 : PointerIsValid(SysCache[cacheId]));
823 : Assert(SysCache[cacheId]->cc_nkeys == 1);
824 :
825 80298590 : return SearchCatCache1(SysCache[cacheId], key1);
826 : }
827 :
828 : HeapTuple
829 8462100 : SearchSysCache2(int cacheId,
830 : Datum key1, Datum key2)
831 : {
832 : Assert(cacheId >= 0 && cacheId < SysCacheSize &&
833 : PointerIsValid(SysCache[cacheId]));
834 : Assert(SysCache[cacheId]->cc_nkeys == 2);
835 :
836 8462100 : return SearchCatCache2(SysCache[cacheId], key1, key2);
837 : }
838 :
839 : HeapTuple
840 4191554 : SearchSysCache3(int cacheId,
841 : Datum key1, Datum key2, Datum key3)
842 : {
843 : Assert(cacheId >= 0 && cacheId < SysCacheSize &&
844 : PointerIsValid(SysCache[cacheId]));
845 : Assert(SysCache[cacheId]->cc_nkeys == 3);
846 :
847 4191554 : return SearchCatCache3(SysCache[cacheId], key1, key2, key3);
848 : }
849 :
850 : HeapTuple
851 3676606 : SearchSysCache4(int cacheId,
852 : Datum key1, Datum key2, Datum key3, Datum key4)
853 : {
854 : Assert(cacheId >= 0 && cacheId < SysCacheSize &&
855 : PointerIsValid(SysCache[cacheId]));
856 : Assert(SysCache[cacheId]->cc_nkeys == 4);
857 :
858 3676606 : return SearchCatCache4(SysCache[cacheId], key1, key2, key3, key4);
859 : }
860 :
861 : /*
862 : * ReleaseSysCache
863 : * Release previously grabbed reference count on a tuple
864 : */
865 : void
866 95158806 : ReleaseSysCache(HeapTuple tuple)
867 : {
868 95158806 : ReleaseCatCache(tuple);
869 95158806 : }
870 :
871 : /*
872 : * SearchSysCacheCopy
873 : *
874 : * A convenience routine that does SearchSysCache and (if successful)
875 : * returns a modifiable copy of the syscache entry. The original
876 : * syscache entry is released before returning. The caller should
877 : * heap_freetuple() the result when done with it.
878 : */
879 : HeapTuple
880 1257866 : SearchSysCacheCopy(int cacheId,
881 : Datum key1,
882 : Datum key2,
883 : Datum key3,
884 : Datum key4)
885 : {
886 : HeapTuple tuple,
887 : newtuple;
888 :
889 1257866 : tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
890 1257866 : if (!HeapTupleIsValid(tuple))
891 332190 : return tuple;
892 925676 : newtuple = heap_copytuple(tuple);
893 925676 : ReleaseSysCache(tuple);
894 925676 : return newtuple;
895 : }
896 :
897 : /*
898 : * SearchSysCacheExists
899 : *
900 : * A convenience routine that just probes to see if a tuple can be found.
901 : * No lock is retained on the syscache entry.
902 : */
903 : bool
904 1227102 : SearchSysCacheExists(int cacheId,
905 : Datum key1,
906 : Datum key2,
907 : Datum key3,
908 : Datum key4)
909 : {
910 : HeapTuple tuple;
911 :
912 1227102 : tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
913 1227102 : if (!HeapTupleIsValid(tuple))
914 301806 : return false;
915 925296 : ReleaseSysCache(tuple);
916 925296 : return true;
917 : }
918 :
919 : /*
920 : * GetSysCacheOid
921 : *
922 : * A convenience routine that does SearchSysCache and returns the OID in the
923 : * oidcol column of the found tuple, or InvalidOid if no tuple could be found.
924 : * No lock is retained on the syscache entry.
925 : */
926 : Oid
927 6307276 : GetSysCacheOid(int cacheId,
928 : AttrNumber oidcol,
929 : Datum key1,
930 : Datum key2,
931 : Datum key3,
932 : Datum key4)
933 : {
934 : HeapTuple tuple;
935 : bool isNull;
936 : Oid result;
937 :
938 6307276 : tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
939 6307276 : if (!HeapTupleIsValid(tuple))
940 3058154 : return InvalidOid;
941 6498244 : result = heap_getattr(tuple, oidcol,
942 3249122 : SysCache[cacheId]->cc_tupdesc,
943 : &isNull);
944 : Assert(!isNull); /* columns used as oids should never be NULL */
945 3249122 : ReleaseSysCache(tuple);
946 3249122 : return result;
947 : }
948 :
949 :
950 : /*
951 : * SearchSysCacheAttName
952 : *
953 : * This routine is equivalent to SearchSysCache on the ATTNAME cache,
954 : * except that it will return NULL if the found attribute is marked
955 : * attisdropped. This is convenient for callers that want to act as
956 : * though dropped attributes don't exist.
957 : */
958 : HeapTuple
959 236784 : SearchSysCacheAttName(Oid relid, const char *attname)
960 : {
961 : HeapTuple tuple;
962 :
963 236784 : tuple = SearchSysCache2(ATTNAME,
964 : ObjectIdGetDatum(relid),
965 : CStringGetDatum(attname));
966 236784 : if (!HeapTupleIsValid(tuple))
967 820 : return NULL;
968 235964 : if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
969 : {
970 78 : ReleaseSysCache(tuple);
971 78 : return NULL;
972 : }
973 235886 : return tuple;
974 : }
975 :
976 : /*
977 : * SearchSysCacheCopyAttName
978 : *
979 : * As above, an attisdropped-aware version of SearchSysCacheCopy.
980 : */
981 : HeapTuple
982 58692 : SearchSysCacheCopyAttName(Oid relid, const char *attname)
983 : {
984 : HeapTuple tuple,
985 : newtuple;
986 :
987 58692 : tuple = SearchSysCacheAttName(relid, attname);
988 58692 : if (!HeapTupleIsValid(tuple))
989 666 : return tuple;
990 58026 : newtuple = heap_copytuple(tuple);
991 58026 : ReleaseSysCache(tuple);
992 58026 : return newtuple;
993 : }
994 :
995 : /*
996 : * SearchSysCacheExistsAttName
997 : *
998 : * As above, an attisdropped-aware version of SearchSysCacheExists.
999 : */
1000 : bool
1001 792 : SearchSysCacheExistsAttName(Oid relid, const char *attname)
1002 : {
1003 : HeapTuple tuple;
1004 :
1005 792 : tuple = SearchSysCacheAttName(relid, attname);
1006 792 : if (!HeapTupleIsValid(tuple))
1007 12 : return false;
1008 780 : ReleaseSysCache(tuple);
1009 780 : return true;
1010 : }
1011 :
1012 :
1013 : /*
1014 : * SearchSysCacheAttNum
1015 : *
1016 : * This routine is equivalent to SearchSysCache on the ATTNUM cache,
1017 : * except that it will return NULL if the found attribute is marked
1018 : * attisdropped. This is convenient for callers that want to act as
1019 : * though dropped attributes don't exist.
1020 : */
1021 : HeapTuple
1022 92 : SearchSysCacheAttNum(Oid relid, int16 attnum)
1023 : {
1024 : HeapTuple tuple;
1025 :
1026 92 : tuple = SearchSysCache2(ATTNUM,
1027 : ObjectIdGetDatum(relid),
1028 : Int16GetDatum(attnum));
1029 92 : if (!HeapTupleIsValid(tuple))
1030 12 : return NULL;
1031 80 : if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
1032 : {
1033 0 : ReleaseSysCache(tuple);
1034 0 : return NULL;
1035 : }
1036 80 : return tuple;
1037 : }
1038 :
1039 : /*
1040 : * SearchSysCacheCopyAttNum
1041 : *
1042 : * As above, an attisdropped-aware version of SearchSysCacheCopy.
1043 : */
1044 : HeapTuple
1045 92 : SearchSysCacheCopyAttNum(Oid relid, int16 attnum)
1046 : {
1047 : HeapTuple tuple,
1048 : newtuple;
1049 :
1050 92 : tuple = SearchSysCacheAttNum(relid, attnum);
1051 92 : if (!HeapTupleIsValid(tuple))
1052 12 : return NULL;
1053 80 : newtuple = heap_copytuple(tuple);
1054 80 : ReleaseSysCache(tuple);
1055 80 : return newtuple;
1056 : }
1057 :
1058 :
1059 : /*
1060 : * SysCacheGetAttr
1061 : *
1062 : * Given a tuple previously fetched by SearchSysCache(),
1063 : * extract a specific attribute.
1064 : *
1065 : * This is equivalent to using heap_getattr() on a tuple fetched
1066 : * from a non-cached relation. Usually, this is only used for attributes
1067 : * that could be NULL or variable length; the fixed-size attributes in
1068 : * a system table are accessed just by mapping the tuple onto the C struct
1069 : * declarations from include/catalog/.
1070 : *
1071 : * As with heap_getattr(), if the attribute is of a pass-by-reference type
1072 : * then a pointer into the tuple data area is returned --- the caller must
1073 : * not modify or pfree the datum!
1074 : *
1075 : * Note: it is legal to use SysCacheGetAttr() with a cacheId referencing
1076 : * a different cache for the same catalog the tuple was fetched from.
1077 : */
1078 : Datum
1079 5516380 : SysCacheGetAttr(int cacheId, HeapTuple tup,
1080 : AttrNumber attributeNumber,
1081 : bool *isNull)
1082 : {
1083 : /*
1084 : * We just need to get the TupleDesc out of the cache entry, and then we
1085 : * can apply heap_getattr(). Normally the cache control data is already
1086 : * valid (because the caller recently fetched the tuple via this same
1087 : * cache), but there are cases where we have to initialize the cache here.
1088 : */
1089 5516380 : if (cacheId < 0 || cacheId >= SysCacheSize ||
1090 5516380 : !PointerIsValid(SysCache[cacheId]))
1091 0 : elog(ERROR, "invalid cache ID: %d", cacheId);
1092 5516380 : if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
1093 : {
1094 22330 : InitCatCachePhase2(SysCache[cacheId], false);
1095 : Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
1096 : }
1097 :
1098 11032760 : return heap_getattr(tup, attributeNumber,
1099 5516380 : SysCache[cacheId]->cc_tupdesc,
1100 : isNull);
1101 : }
1102 :
1103 : /*
1104 : * SysCacheGetAttrNotNull
1105 : *
1106 : * As above, a version of SysCacheGetAttr which knows that the attr cannot
1107 : * be NULL.
1108 : */
1109 : Datum
1110 2916604 : SysCacheGetAttrNotNull(int cacheId, HeapTuple tup,
1111 : AttrNumber attributeNumber)
1112 : {
1113 : bool isnull;
1114 : Datum attr;
1115 :
1116 2916604 : attr = SysCacheGetAttr(cacheId, tup, attributeNumber, &isnull);
1117 :
1118 2916604 : if (isnull)
1119 : {
1120 0 : elog(ERROR,
1121 : "unexpected null value in cached tuple for catalog %s column %s",
1122 : get_rel_name(cacheinfo[cacheId].reloid),
1123 : NameStr(TupleDescAttr(SysCache[cacheId]->cc_tupdesc, attributeNumber - 1)->attname));
1124 : }
1125 :
1126 2916604 : return attr;
1127 : }
1128 :
1129 : /*
1130 : * GetSysCacheHashValue
1131 : *
1132 : * Get the hash value that would be used for a tuple in the specified cache
1133 : * with the given search keys.
1134 : *
1135 : * The reason for exposing this as part of the API is that the hash value is
1136 : * exposed in cache invalidation operations, so there are places outside the
1137 : * catcache code that need to be able to compute the hash values.
1138 : */
1139 : uint32
1140 214786 : GetSysCacheHashValue(int cacheId,
1141 : Datum key1,
1142 : Datum key2,
1143 : Datum key3,
1144 : Datum key4)
1145 : {
1146 214786 : if (cacheId < 0 || cacheId >= SysCacheSize ||
1147 214786 : !PointerIsValid(SysCache[cacheId]))
1148 0 : elog(ERROR, "invalid cache ID: %d", cacheId);
1149 :
1150 214786 : return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
1151 : }
1152 :
1153 : /*
1154 : * List-search interface
1155 : */
1156 : struct catclist *
1157 3117474 : SearchSysCacheList(int cacheId, int nkeys,
1158 : Datum key1, Datum key2, Datum key3)
1159 : {
1160 3117474 : if (cacheId < 0 || cacheId >= SysCacheSize ||
1161 3117474 : !PointerIsValid(SysCache[cacheId]))
1162 0 : elog(ERROR, "invalid cache ID: %d", cacheId);
1163 :
1164 3117474 : return SearchCatCacheList(SysCache[cacheId], nkeys,
1165 : key1, key2, key3);
1166 : }
1167 :
1168 : /*
1169 : * SysCacheInvalidate
1170 : *
1171 : * Invalidate entries in the specified cache, given a hash value.
1172 : * See CatCacheInvalidate() for more info.
1173 : *
1174 : * This routine is only quasi-public: it should only be used by inval.c.
1175 : */
1176 : void
1177 25035450 : SysCacheInvalidate(int cacheId, uint32 hashValue)
1178 : {
1179 25035450 : if (cacheId < 0 || cacheId >= SysCacheSize)
1180 0 : elog(ERROR, "invalid cache ID: %d", cacheId);
1181 :
1182 : /* if this cache isn't initialized yet, no need to do anything */
1183 25035450 : if (!PointerIsValid(SysCache[cacheId]))
1184 0 : return;
1185 :
1186 25035450 : CatCacheInvalidate(SysCache[cacheId], hashValue);
1187 : }
1188 :
1189 : /*
1190 : * Certain relations that do not have system caches send snapshot invalidation
1191 : * messages in lieu of catcache messages. This is for the benefit of
1192 : * GetCatalogSnapshot(), which can then reuse its existing MVCC snapshot
1193 : * for scanning one of those catalogs, rather than taking a new one, if no
1194 : * invalidation has been received.
1195 : *
1196 : * Relations that have syscaches need not (and must not) be listed here. The
1197 : * catcache invalidation messages will also flush the snapshot. If you add a
1198 : * syscache for one of these relations, remove it from this list.
1199 : */
1200 : bool
1201 21084520 : RelationInvalidatesSnapshotsOnly(Oid relid)
1202 : {
1203 21084520 : switch (relid)
1204 : {
1205 4018762 : case DbRoleSettingRelationId:
1206 : case DependRelationId:
1207 : case SharedDependRelationId:
1208 : case DescriptionRelationId:
1209 : case SharedDescriptionRelationId:
1210 : case SecLabelRelationId:
1211 : case SharedSecLabelRelationId:
1212 4018762 : return true;
1213 17065758 : default:
1214 17065758 : break;
1215 : }
1216 :
1217 17065758 : return false;
1218 : }
1219 :
1220 : /*
1221 : * Test whether a relation has a system cache.
1222 : */
1223 : bool
1224 12036080 : RelationHasSysCache(Oid relid)
1225 : {
1226 12036080 : int low = 0,
1227 12036080 : high = SysCacheRelationOidSize - 1;
1228 :
1229 53583876 : while (low <= high)
1230 : {
1231 53210278 : int middle = low + (high - low) / 2;
1232 :
1233 53210278 : if (SysCacheRelationOid[middle] == relid)
1234 11662482 : return true;
1235 41547796 : if (SysCacheRelationOid[middle] < relid)
1236 14894208 : low = middle + 1;
1237 : else
1238 26653588 : high = middle - 1;
1239 : }
1240 :
1241 373598 : return false;
1242 : }
1243 :
1244 : /*
1245 : * Test whether a relation supports a system cache, ie it is either a
1246 : * cached table or the index used for a cache.
1247 : */
1248 : bool
1249 3099104 : RelationSupportsSysCache(Oid relid)
1250 : {
1251 3099104 : int low = 0,
1252 3099104 : high = SysCacheSupportingRelOidSize - 1;
1253 :
1254 26279474 : while (low <= high)
1255 : {
1256 23693272 : int middle = low + (high - low) / 2;
1257 :
1258 23693272 : if (SysCacheSupportingRelOid[middle] == relid)
1259 512902 : return true;
1260 23180370 : if (SysCacheSupportingRelOid[middle] < relid)
1261 21442650 : low = middle + 1;
1262 : else
1263 1737720 : high = middle - 1;
1264 : }
1265 :
1266 2586202 : return false;
1267 : }
1268 :
1269 :
1270 : /*
1271 : * OID comparator for pg_qsort
1272 : */
1273 : static int
1274 45620328 : oid_compare(const void *a, const void *b)
1275 : {
1276 45620328 : Oid oa = *((const Oid *) a);
1277 45620328 : Oid ob = *((const Oid *) b);
1278 :
1279 45620328 : if (oa == ob)
1280 3869796 : return 0;
1281 41750532 : return (oa > ob) ? 1 : -1;
1282 : }
|