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 24214 : InitCatalogCache(void)
710 : {
711 : int cacheId;
712 :
713 : Assert(!CacheInitialized);
714 :
715 24214 : SysCacheRelationOidSize = SysCacheSupportingRelOidSize = 0;
716 :
717 2033976 : 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(OidIsValid(cacheinfo[cacheId].reloid));
724 : Assert(OidIsValid(cacheinfo[cacheId].indoid));
725 : /* .nbuckets and .key[] are checked by InitCatCache() */
726 :
727 4019524 : SysCache[cacheId] = InitCatCache(cacheId,
728 : cacheinfo[cacheId].reloid,
729 : cacheinfo[cacheId].indoid,
730 : cacheinfo[cacheId].nkeys,
731 2009762 : cacheinfo[cacheId].key,
732 : cacheinfo[cacheId].nbuckets);
733 2009762 : if (!PointerIsValid(SysCache[cacheId]))
734 0 : elog(ERROR, "could not initialize cache %u (%d)",
735 : cacheinfo[cacheId].reloid, cacheId);
736 : /* Accumulate data for OID lists, too */
737 2009762 : SysCacheRelationOid[SysCacheRelationOidSize++] =
738 2009762 : cacheinfo[cacheId].reloid;
739 2009762 : SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
740 2009762 : cacheinfo[cacheId].reloid;
741 2009762 : SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
742 2009762 : cacheinfo[cacheId].indoid;
743 : /* see comments for RelationInvalidatesSnapshotsOnly */
744 : Assert(!RelationInvalidatesSnapshotsOnly(cacheinfo[cacheId].reloid));
745 : }
746 :
747 : Assert(SysCacheRelationOidSize <= lengthof(SysCacheRelationOid));
748 : Assert(SysCacheSupportingRelOidSize <= lengthof(SysCacheSupportingRelOid));
749 :
750 : /* Sort and de-dup OID arrays, so we can use binary search. */
751 24214 : pg_qsort(SysCacheRelationOid, SysCacheRelationOidSize,
752 : sizeof(Oid), oid_compare);
753 24214 : SysCacheRelationOidSize =
754 24214 : qunique(SysCacheRelationOid, SysCacheRelationOidSize, sizeof(Oid),
755 : oid_compare);
756 :
757 24214 : pg_qsort(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
758 : sizeof(Oid), oid_compare);
759 24214 : SysCacheSupportingRelOidSize =
760 24214 : qunique(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
761 : sizeof(Oid), oid_compare);
762 :
763 24214 : CacheInitialized = true;
764 24214 : }
765 :
766 : /*
767 : * InitCatalogCachePhase2 - finish initializing the caches
768 : *
769 : * Finish initializing all the caches, including necessary database
770 : * access.
771 : *
772 : * This is *not* essential; normally we allow syscaches to be initialized
773 : * on first use. However, it is useful as a mechanism to preload the
774 : * relcache with entries for the most-commonly-used system catalogs.
775 : * Therefore, we invoke this routine when we need to write a new relcache
776 : * init file.
777 : */
778 : void
779 1918 : InitCatalogCachePhase2(void)
780 : {
781 : int cacheId;
782 :
783 : Assert(CacheInitialized);
784 :
785 160972 : for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
786 159056 : InitCatCachePhase2(SysCache[cacheId], true);
787 1916 : }
788 :
789 :
790 : /*
791 : * SearchSysCache
792 : *
793 : * A layer on top of SearchCatCache that does the initialization and
794 : * key-setting for you.
795 : *
796 : * Returns the cache copy of the tuple if one is found, NULL if not.
797 : * The tuple is the 'cache' copy and must NOT be modified!
798 : *
799 : * When the caller is done using the tuple, call ReleaseSysCache()
800 : * to release the reference count grabbed by SearchSysCache(). If this
801 : * is not done, the tuple will remain locked in cache until end of
802 : * transaction, which is tolerable but not desirable.
803 : *
804 : * CAUTION: The tuple that is returned must NOT be freed by the caller!
805 : */
806 : HeapTuple
807 4308924 : SearchSysCache(int cacheId,
808 : Datum key1,
809 : Datum key2,
810 : Datum key3,
811 : Datum key4)
812 : {
813 : Assert(cacheId >= 0 && cacheId < SysCacheSize &&
814 : PointerIsValid(SysCache[cacheId]));
815 :
816 4308924 : return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
817 : }
818 :
819 : HeapTuple
820 53256460 : SearchSysCache1(int cacheId,
821 : Datum key1)
822 : {
823 : Assert(cacheId >= 0 && cacheId < SysCacheSize &&
824 : PointerIsValid(SysCache[cacheId]));
825 : Assert(SysCache[cacheId]->cc_nkeys == 1);
826 :
827 53256460 : return SearchCatCache1(SysCache[cacheId], key1);
828 : }
829 :
830 : HeapTuple
831 4023942 : SearchSysCache2(int cacheId,
832 : Datum key1, Datum key2)
833 : {
834 : Assert(cacheId >= 0 && cacheId < SysCacheSize &&
835 : PointerIsValid(SysCache[cacheId]));
836 : Assert(SysCache[cacheId]->cc_nkeys == 2);
837 :
838 4023942 : return SearchCatCache2(SysCache[cacheId], key1, key2);
839 : }
840 :
841 : HeapTuple
842 4121072 : SearchSysCache3(int cacheId,
843 : Datum key1, Datum key2, Datum key3)
844 : {
845 : Assert(cacheId >= 0 && cacheId < SysCacheSize &&
846 : PointerIsValid(SysCache[cacheId]));
847 : Assert(SysCache[cacheId]->cc_nkeys == 3);
848 :
849 4121072 : return SearchCatCache3(SysCache[cacheId], key1, key2, key3);
850 : }
851 :
852 : HeapTuple
853 3192638 : SearchSysCache4(int cacheId,
854 : Datum key1, Datum key2, Datum key3, Datum key4)
855 : {
856 : Assert(cacheId >= 0 && cacheId < SysCacheSize &&
857 : PointerIsValid(SysCache[cacheId]));
858 : Assert(SysCache[cacheId]->cc_nkeys == 4);
859 :
860 3192638 : return SearchCatCache4(SysCache[cacheId], key1, key2, key3, key4);
861 : }
862 :
863 : /*
864 : * ReleaseSysCache
865 : * Release previously grabbed reference count on a tuple
866 : */
867 : void
868 64424452 : ReleaseSysCache(HeapTuple tuple)
869 : {
870 64424452 : ReleaseCatCache(tuple);
871 64424452 : }
872 :
873 : /*
874 : * SearchSysCacheCopy
875 : *
876 : * A convenience routine that does SearchSysCache and (if successful)
877 : * returns a modifiable copy of the syscache entry. The original
878 : * syscache entry is released before returning. The caller should
879 : * heap_freetuple() the result when done with it.
880 : */
881 : HeapTuple
882 419800 : SearchSysCacheCopy(int cacheId,
883 : Datum key1,
884 : Datum key2,
885 : Datum key3,
886 : Datum key4)
887 : {
888 : HeapTuple tuple,
889 : newtuple;
890 :
891 419800 : tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
892 419800 : if (!HeapTupleIsValid(tuple))
893 106534 : return tuple;
894 313266 : newtuple = heap_copytuple(tuple);
895 313266 : ReleaseSysCache(tuple);
896 313266 : return newtuple;
897 : }
898 :
899 : /*
900 : * SearchSysCacheExists
901 : *
902 : * A convenience routine that just probes to see if a tuple can be found.
903 : * No lock is retained on the syscache entry.
904 : */
905 : bool
906 1024596 : SearchSysCacheExists(int cacheId,
907 : Datum key1,
908 : Datum key2,
909 : Datum key3,
910 : Datum key4)
911 : {
912 : HeapTuple tuple;
913 :
914 1024596 : tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
915 1024596 : if (!HeapTupleIsValid(tuple))
916 201088 : return false;
917 823508 : ReleaseSysCache(tuple);
918 823508 : return true;
919 : }
920 :
921 : /*
922 : * GetSysCacheOid
923 : *
924 : * A convenience routine that does SearchSysCache and returns the OID in the
925 : * oidcol column of the found tuple, or InvalidOid if no tuple could be found.
926 : * No lock is retained on the syscache entry.
927 : */
928 : Oid
929 2864528 : GetSysCacheOid(int cacheId,
930 : AttrNumber oidcol,
931 : Datum key1,
932 : Datum key2,
933 : Datum key3,
934 : Datum key4)
935 : {
936 : HeapTuple tuple;
937 : bool isNull;
938 : Oid result;
939 :
940 2864528 : tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
941 2864528 : if (!HeapTupleIsValid(tuple))
942 1145688 : return InvalidOid;
943 3437680 : result = heap_getattr(tuple, oidcol,
944 1718840 : SysCache[cacheId]->cc_tupdesc,
945 : &isNull);
946 : Assert(!isNull); /* columns used as oids should never be NULL */
947 1718840 : ReleaseSysCache(tuple);
948 1718840 : return result;
949 : }
950 :
951 :
952 : /*
953 : * SearchSysCacheAttName
954 : *
955 : * This routine is equivalent to SearchSysCache on the ATTNAME cache,
956 : * except that it will return NULL if the found attribute is marked
957 : * attisdropped. This is convenient for callers that want to act as
958 : * though dropped attributes don't exist.
959 : */
960 : HeapTuple
961 87916 : SearchSysCacheAttName(Oid relid, const char *attname)
962 : {
963 : HeapTuple tuple;
964 :
965 87916 : tuple = SearchSysCache2(ATTNAME,
966 : ObjectIdGetDatum(relid),
967 : CStringGetDatum(attname));
968 87916 : if (!HeapTupleIsValid(tuple))
969 826 : return NULL;
970 87090 : if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
971 : {
972 78 : ReleaseSysCache(tuple);
973 78 : return NULL;
974 : }
975 87012 : return tuple;
976 : }
977 :
978 : /*
979 : * SearchSysCacheCopyAttName
980 : *
981 : * As above, an attisdropped-aware version of SearchSysCacheCopy.
982 : */
983 : HeapTuple
984 8184 : SearchSysCacheCopyAttName(Oid relid, const char *attname)
985 : {
986 : HeapTuple tuple,
987 : newtuple;
988 :
989 8184 : tuple = SearchSysCacheAttName(relid, attname);
990 8184 : if (!HeapTupleIsValid(tuple))
991 636 : return tuple;
992 7548 : newtuple = heap_copytuple(tuple);
993 7548 : ReleaseSysCache(tuple);
994 7548 : return newtuple;
995 : }
996 :
997 : /*
998 : * SearchSysCacheExistsAttName
999 : *
1000 : * As above, an attisdropped-aware version of SearchSysCacheExists.
1001 : */
1002 : bool
1003 798 : SearchSysCacheExistsAttName(Oid relid, const char *attname)
1004 : {
1005 : HeapTuple tuple;
1006 :
1007 798 : tuple = SearchSysCacheAttName(relid, attname);
1008 798 : if (!HeapTupleIsValid(tuple))
1009 12 : return false;
1010 786 : ReleaseSysCache(tuple);
1011 786 : return true;
1012 : }
1013 :
1014 :
1015 : /*
1016 : * SearchSysCacheAttNum
1017 : *
1018 : * This routine is equivalent to SearchSysCache on the ATTNUM cache,
1019 : * except that it will return NULL if the found attribute is marked
1020 : * attisdropped. This is convenient for callers that want to act as
1021 : * though dropped attributes don't exist.
1022 : */
1023 : HeapTuple
1024 21224 : SearchSysCacheAttNum(Oid relid, int16 attnum)
1025 : {
1026 : HeapTuple tuple;
1027 :
1028 21224 : tuple = SearchSysCache2(ATTNUM,
1029 : ObjectIdGetDatum(relid),
1030 : Int16GetDatum(attnum));
1031 21224 : if (!HeapTupleIsValid(tuple))
1032 12 : return NULL;
1033 21212 : if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
1034 : {
1035 0 : ReleaseSysCache(tuple);
1036 0 : return NULL;
1037 : }
1038 21212 : return tuple;
1039 : }
1040 :
1041 : /*
1042 : * SearchSysCacheCopyAttNum
1043 : *
1044 : * As above, an attisdropped-aware version of SearchSysCacheCopy.
1045 : */
1046 : HeapTuple
1047 21224 : SearchSysCacheCopyAttNum(Oid relid, int16 attnum)
1048 : {
1049 : HeapTuple tuple,
1050 : newtuple;
1051 :
1052 21224 : tuple = SearchSysCacheAttNum(relid, attnum);
1053 21224 : if (!HeapTupleIsValid(tuple))
1054 12 : return NULL;
1055 21212 : newtuple = heap_copytuple(tuple);
1056 21212 : ReleaseSysCache(tuple);
1057 21212 : return newtuple;
1058 : }
1059 :
1060 :
1061 : /*
1062 : * SysCacheGetAttr
1063 : *
1064 : * Given a tuple previously fetched by SearchSysCache(),
1065 : * extract a specific attribute.
1066 : *
1067 : * This is equivalent to using heap_getattr() on a tuple fetched
1068 : * from a non-cached relation. Usually, this is only used for attributes
1069 : * that could be NULL or variable length; the fixed-size attributes in
1070 : * a system table are accessed just by mapping the tuple onto the C struct
1071 : * declarations from include/catalog/.
1072 : *
1073 : * As with heap_getattr(), if the attribute is of a pass-by-reference type
1074 : * then a pointer into the tuple data area is returned --- the caller must
1075 : * not modify or pfree the datum!
1076 : *
1077 : * Note: it is legal to use SysCacheGetAttr() with a cacheId referencing
1078 : * a different cache for the same catalog the tuple was fetched from.
1079 : */
1080 : Datum
1081 4161828 : SysCacheGetAttr(int cacheId, HeapTuple tup,
1082 : AttrNumber attributeNumber,
1083 : bool *isNull)
1084 : {
1085 : /*
1086 : * We just need to get the TupleDesc out of the cache entry, and then we
1087 : * can apply heap_getattr(). Normally the cache control data is already
1088 : * valid (because the caller recently fetched the tuple via this same
1089 : * cache), but there are cases where we have to initialize the cache here.
1090 : */
1091 4161828 : if (cacheId < 0 || cacheId >= SysCacheSize ||
1092 4161828 : !PointerIsValid(SysCache[cacheId]))
1093 0 : elog(ERROR, "invalid cache ID: %d", cacheId);
1094 4161828 : if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
1095 : {
1096 23024 : InitCatCachePhase2(SysCache[cacheId], false);
1097 : Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
1098 : }
1099 :
1100 8323656 : return heap_getattr(tup, attributeNumber,
1101 4161828 : SysCache[cacheId]->cc_tupdesc,
1102 : isNull);
1103 : }
1104 :
1105 : /*
1106 : * SysCacheGetAttrNotNull
1107 : *
1108 : * As above, a version of SysCacheGetAttr which knows that the attr cannot
1109 : * be NULL.
1110 : */
1111 : Datum
1112 2503956 : SysCacheGetAttrNotNull(int cacheId, HeapTuple tup,
1113 : AttrNumber attributeNumber)
1114 : {
1115 : bool isnull;
1116 : Datum attr;
1117 :
1118 2503956 : attr = SysCacheGetAttr(cacheId, tup, attributeNumber, &isnull);
1119 :
1120 2503956 : if (isnull)
1121 : {
1122 0 : elog(ERROR,
1123 : "unexpected null value in cached tuple for catalog %s column %s",
1124 : get_rel_name(cacheinfo[cacheId].reloid),
1125 : NameStr(TupleDescAttr(SysCache[cacheId]->cc_tupdesc, attributeNumber - 1)->attname));
1126 : }
1127 :
1128 2503956 : return attr;
1129 : }
1130 :
1131 : /*
1132 : * GetSysCacheHashValue
1133 : *
1134 : * Get the hash value that would be used for a tuple in the specified cache
1135 : * with the given search keys.
1136 : *
1137 : * The reason for exposing this as part of the API is that the hash value is
1138 : * exposed in cache invalidation operations, so there are places outside the
1139 : * catcache code that need to be able to compute the hash values.
1140 : */
1141 : uint32
1142 133450 : GetSysCacheHashValue(int cacheId,
1143 : Datum key1,
1144 : Datum key2,
1145 : Datum key3,
1146 : Datum key4)
1147 : {
1148 133450 : if (cacheId < 0 || cacheId >= SysCacheSize ||
1149 133450 : !PointerIsValid(SysCache[cacheId]))
1150 0 : elog(ERROR, "invalid cache ID: %d", cacheId);
1151 :
1152 133450 : return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
1153 : }
1154 :
1155 : /*
1156 : * List-search interface
1157 : */
1158 : struct catclist *
1159 2747382 : SearchSysCacheList(int cacheId, int nkeys,
1160 : Datum key1, Datum key2, Datum key3)
1161 : {
1162 2747382 : if (cacheId < 0 || cacheId >= SysCacheSize ||
1163 2747382 : !PointerIsValid(SysCache[cacheId]))
1164 0 : elog(ERROR, "invalid cache ID: %d", cacheId);
1165 :
1166 2747382 : return SearchCatCacheList(SysCache[cacheId], nkeys,
1167 : key1, key2, key3);
1168 : }
1169 :
1170 : /*
1171 : * SysCacheInvalidate
1172 : *
1173 : * Invalidate entries in the specified cache, given a hash value.
1174 : * See CatCacheInvalidate() for more info.
1175 : *
1176 : * This routine is only quasi-public: it should only be used by inval.c.
1177 : */
1178 : void
1179 16033556 : SysCacheInvalidate(int cacheId, uint32 hashValue)
1180 : {
1181 16033556 : if (cacheId < 0 || cacheId >= SysCacheSize)
1182 0 : elog(ERROR, "invalid cache ID: %d", cacheId);
1183 :
1184 : /* if this cache isn't initialized yet, no need to do anything */
1185 16033556 : if (!PointerIsValid(SysCache[cacheId]))
1186 0 : return;
1187 :
1188 16033556 : CatCacheInvalidate(SysCache[cacheId], hashValue);
1189 : }
1190 :
1191 : /*
1192 : * Certain relations that do not have system caches send snapshot invalidation
1193 : * messages in lieu of catcache messages. This is for the benefit of
1194 : * GetCatalogSnapshot(), which can then reuse its existing MVCC snapshot
1195 : * for scanning one of those catalogs, rather than taking a new one, if no
1196 : * invalidation has been received.
1197 : *
1198 : * Relations that have syscaches need not (and must not) be listed here. The
1199 : * catcache invalidation messages will also flush the snapshot. If you add a
1200 : * syscache for one of these relations, remove it from this list.
1201 : */
1202 : bool
1203 11252592 : RelationInvalidatesSnapshotsOnly(Oid relid)
1204 : {
1205 11252592 : switch (relid)
1206 : {
1207 2018366 : case DbRoleSettingRelationId:
1208 : case DependRelationId:
1209 : case SharedDependRelationId:
1210 : case DescriptionRelationId:
1211 : case SharedDescriptionRelationId:
1212 : case SecLabelRelationId:
1213 : case SharedSecLabelRelationId:
1214 2018366 : return true;
1215 9234226 : default:
1216 9234226 : break;
1217 : }
1218 :
1219 9234226 : return false;
1220 : }
1221 :
1222 : /*
1223 : * Test whether a relation has a system cache.
1224 : */
1225 : bool
1226 6900520 : RelationHasSysCache(Oid relid)
1227 : {
1228 6900520 : int low = 0,
1229 6900520 : high = SysCacheRelationOidSize - 1;
1230 :
1231 30470134 : while (low <= high)
1232 : {
1233 30084582 : int middle = low + (high - low) / 2;
1234 :
1235 30084582 : if (SysCacheRelationOid[middle] == relid)
1236 6514968 : return true;
1237 23569614 : if (SysCacheRelationOid[middle] < relid)
1238 8209368 : low = middle + 1;
1239 : else
1240 15360246 : high = middle - 1;
1241 : }
1242 :
1243 385552 : return false;
1244 : }
1245 :
1246 : /*
1247 : * Test whether a relation supports a system cache, ie it is either a
1248 : * cached table or the index used for a cache.
1249 : */
1250 : bool
1251 1671510 : RelationSupportsSysCache(Oid relid)
1252 : {
1253 1671510 : int low = 0,
1254 1671510 : high = SysCacheSupportingRelOidSize - 1;
1255 :
1256 14329708 : while (low <= high)
1257 : {
1258 12902714 : int middle = low + (high - low) / 2;
1259 :
1260 12902714 : if (SysCacheSupportingRelOid[middle] == relid)
1261 244516 : return true;
1262 12658198 : if (SysCacheSupportingRelOid[middle] < relid)
1263 11968992 : low = middle + 1;
1264 : else
1265 689206 : high = middle - 1;
1266 : }
1267 :
1268 1426994 : return false;
1269 : }
1270 :
1271 :
1272 : /*
1273 : * OID comparator for pg_qsort
1274 : */
1275 : static int
1276 45958172 : oid_compare(const void *a, const void *b)
1277 : {
1278 45958172 : Oid oa = *((const Oid *) a);
1279 45958172 : Oid ob = *((const Oid *) b);
1280 :
1281 45958172 : if (oa == ob)
1282 3898454 : return 0;
1283 42059718 : return (oa > ob) ? 1 : -1;
1284 : }
|