Age Owner TLA 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
840 akorotkov 482 ECB : },
483 : [RANGETYPE] = {
484 : RangeRelationId,
485 : RangeTypidIndexId,
486 : KEY(Anum_pg_range_rngtypid),
487 : 4
488 : },
489 : [RELNAMENSP] = {
490 : RelationRelationId,
2140 tgl 491 : ClassNameNspIndexId,
492 : KEY(Anum_pg_class_relname,
493 : Anum_pg_class_relnamespace),
494 : 128
2271 peter_e 495 EUB : },
496 : [RELOID] = {
497 : RelationRelationId,
498 : ClassOidIndexId,
499 : KEY(Anum_pg_class_oid),
2140 tgl 500 ECB : 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,
2207 alvherre 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,
4842 rhaas 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),
3503 heikki.linnakangas 620 : 2
5710 tgl 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),
3503 heikki.linnakangas 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,
5710 tgl 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),
3503 heikki.linnakangas 659 : 64
6142 tgl 660 : },
661 : [TYPEOID] = {
662 : TypeRelationId,
6569 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
5224 peter_e 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 :
8397 bruce 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;
3568 rhaas 692 :
2863 tgl 693 : /* Sorted array of OIDs of tables and indexes used by caches */
694 : static Oid SysCacheSupportingRelOid[SysCacheSize * 2];
695 : static int SysCacheSupportingRelOidSize;
696 :
3260 bruce 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
8179 tgl 709 GIC 11570 : InitCatalogCache(void)
710 : {
711 : int cacheId;
712 :
713 11570 : Assert(!CacheInitialized);
714 :
2863 715 11570 : SysCacheRelationOidSize = SysCacheSupportingRelOidSize = 0;
716 :
8179 717 971880 : for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
9345 bruce 718 ECB : {
719 : /*
720 : * Assert that every enumeration value defined in syscache.h has been
721 : * populated in the cacheinfo array.
722 : */
107 tmunro 723 GNC 960310 : Assert(cacheinfo[cacheId].reloid != 0);
724 :
8179 tgl 725 GIC 1920620 : SysCache[cacheId] = InitCatCache(cacheId,
6569 726 960310 : cacheinfo[cacheId].reloid,
727 960310 : cacheinfo[cacheId].indoid,
8179 728 960310 : cacheinfo[cacheId].nkeys,
6142 729 960310 : cacheinfo[cacheId].key,
730 960310 : cacheinfo[cacheId].nbuckets);
8179 731 960310 : if (!PointerIsValid(SysCache[cacheId]))
6569 tgl 732 UIC 0 : elog(ERROR, "could not initialize cache %u (%d)",
733 : cacheinfo[cacheId].reloid, cacheId);
2863 tgl 734 ECB : /* Accumulate data for OID lists, too */
3568 rhaas 735 CBC 960310 : SysCacheRelationOid[SysCacheRelationOidSize++] =
3568 rhaas 736 GBC 960310 : cacheinfo[cacheId].reloid;
2863 tgl 737 CBC 960310 : SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
2863 tgl 738 GIC 960310 : cacheinfo[cacheId].reloid;
2863 tgl 739 CBC 960310 : SysCacheSupportingRelOid[SysCacheSupportingRelOidSize++] =
740 960310 : cacheinfo[cacheId].indoid;
741 : /* see comments for RelationInvalidatesSnapshotsOnly */
3568 rhaas 742 GIC 960310 : Assert(!RelationInvalidatesSnapshotsOnly(cacheinfo[cacheId].reloid));
9770 scrappy 743 ECB : }
3568 rhaas 744 :
2863 tgl 745 GIC 11570 : Assert(SysCacheRelationOidSize <= lengthof(SysCacheRelationOid));
746 11570 : Assert(SysCacheSupportingRelOidSize <= lengthof(SysCacheSupportingRelOid));
747 :
748 : /* Sort and de-dup OID arrays, so we can use binary search. */
3568 rhaas 749 11570 : pg_qsort(SysCacheRelationOid, SysCacheRelationOidSize,
750 : sizeof(Oid), oid_compare);
1249 tmunro 751 11570 : SysCacheRelationOidSize =
752 11570 : qunique(SysCacheRelationOid, SysCacheRelationOidSize, sizeof(Oid),
753 : oid_compare);
754 :
2863 tgl 755 CBC 11570 : pg_qsort(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
756 : sizeof(Oid), oid_compare);
1249 tmunro 757 GIC 11570 : SysCacheSupportingRelOidSize =
758 11570 : qunique(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
759 : sizeof(Oid), oid_compare);
760 :
8451 inoue 761 CBC 11570 : CacheInitialized = true;
9770 scrappy 762 GIC 11570 : }
8986 bruce 763 ECB :
764 : /*
7719 tgl 765 EUB : * 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
7719 tgl 771 ECB : * 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
7719 tgl 777 GIC 1227 : InitCatalogCachePhase2(void)
778 : {
779 : int cacheId;
780 :
781 1227 : Assert(CacheInitialized);
782 :
783 103030 : for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
6029 784 101805 : InitCatCachePhase2(SysCache[cacheId], true);
7719 tgl 785 CBC 1225 : }
786 :
787 :
788 : /*
789 : * SearchSysCache
790 : *
8179 tgl 791 ECB : * A layer on top of SearchCatCache that does the initialization and
8999 bruce 792 : * key-setting for you.
9770 scrappy 793 EUB : *
794 : * Returns the cache copy of the tuple if one is found, NULL if not.
8179 tgl 795 ECB : * 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
8179 tgl 805 CBC 4845939 : SearchSysCache(int cacheId,
8179 tgl 806 ECB : Datum key1,
8179 tgl 807 EUB : Datum key2,
808 : Datum key3,
8179 tgl 809 ECB : Datum key4)
810 : {
2004 andres 811 GIC 4845939 : Assert(cacheId >= 0 && cacheId < SysCacheSize &&
812 : PointerIsValid(SysCache[cacheId]));
813 :
8179 tgl 814 4845939 : return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
815 : }
816 :
817 : HeapTuple
2004 andres 818 40450452 : SearchSysCache1(int cacheId,
819 : Datum key1)
820 : {
821 40450452 : Assert(cacheId >= 0 && cacheId < SysCacheSize &&
2004 andres 822 ECB : PointerIsValid(SysCache[cacheId]));
2004 andres 823 GIC 40450452 : Assert(SysCache[cacheId]->cc_nkeys == 1);
2004 andres 824 ECB :
2004 andres 825 GBC 40450452 : return SearchCatCache1(SysCache[cacheId], key1);
826 : }
827 :
2004 andres 828 ECB : HeapTuple
2004 andres 829 GBC 4345637 : SearchSysCache2(int cacheId,
830 : Datum key1, Datum key2)
2004 andres 831 ECB : {
2004 andres 832 GIC 4345637 : Assert(cacheId >= 0 && cacheId < SysCacheSize &&
833 : PointerIsValid(SysCache[cacheId]));
834 4345637 : Assert(SysCache[cacheId]->cc_nkeys == 2);
835 :
836 4345637 : return SearchCatCache2(SysCache[cacheId], key1, key2);
837 : }
838 :
839 : HeapTuple
840 2148760 : SearchSysCache3(int cacheId,
841 : Datum key1, Datum key2, Datum key3)
842 : {
843 2148760 : Assert(cacheId >= 0 && cacheId < SysCacheSize &&
844 : PointerIsValid(SysCache[cacheId]));
845 2148760 : Assert(SysCache[cacheId]->cc_nkeys == 3);
2004 andres 846 ECB :
2004 andres 847 GIC 2148760 : return SearchCatCache3(SysCache[cacheId], key1, key2, key3);
2004 andres 848 ECB : }
849 :
850 : HeapTuple
2004 andres 851 GIC 1886317 : SearchSysCache4(int cacheId,
852 : Datum key1, Datum key2, Datum key3, Datum key4)
853 : {
854 1886317 : Assert(cacheId >= 0 && cacheId < SysCacheSize &&
855 : PointerIsValid(SysCache[cacheId]));
856 1886317 : Assert(SysCache[cacheId]->cc_nkeys == 4);
2004 andres 857 ECB :
2004 andres 858 CBC 1886317 : return SearchCatCache4(SysCache[cacheId], key1, key2, key3, key4);
2004 andres 859 ECB : }
860 :
861 : /*
8179 tgl 862 : * ReleaseSysCache
863 : * Release previously grabbed reference count on a tuple
864 : */
865 : void
8179 tgl 866 GIC 48077091 : ReleaseSysCache(HeapTuple tuple)
867 : {
868 48077091 : ReleaseCatCache(tuple);
8179 tgl 869 CBC 48077091 : }
870 :
8331 tgl 871 ECB : /*
8179 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.
8331 878 : */
879 : HeapTuple
8179 tgl 880 CBC 633804 : SearchSysCacheCopy(int cacheId,
8179 tgl 881 ECB : Datum key1,
882 : Datum key2,
883 : Datum key3,
884 : Datum key4)
885 : {
886 : HeapTuple tuple,
887 : newtuple;
888 :
8179 tgl 889 GIC 633804 : tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
890 633804 : if (!HeapTupleIsValid(tuple))
891 166941 : return tuple;
892 466863 : newtuple = heap_copytuple(tuple);
893 466863 : ReleaseSysCache(tuple);
8179 tgl 894 CBC 466863 : return newtuple;
895 : }
8331 tgl 896 ECB :
7912 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
7912 tgl 904 CBC 612586 : SearchSysCacheExists(int cacheId,
7912 tgl 905 ECB : Datum key1,
906 : Datum key2,
907 : Datum key3,
908 : Datum key4)
909 : {
910 : HeapTuple tuple;
911 :
7912 tgl 912 GIC 612586 : tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
913 612586 : if (!HeapTupleIsValid(tuple))
914 144909 : return false;
915 467677 : ReleaseSysCache(tuple);
916 467677 : return true;
917 : }
918 :
8179 tgl 919 ECB : /*
920 : * GetSysCacheOid
921 : *
1601 andres 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.
8179 tgl 924 : * No lock is retained on the syscache entry.
925 : */
926 : Oid
8179 tgl 927 GIC 3599549 : 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 3599549 : tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
939 3599549 : if (!HeapTupleIsValid(tuple))
940 1949762 : return InvalidOid;
1601 andres 941 3299574 : result = heap_getattr(tuple, oidcol,
942 1649787 : SysCache[cacheId]->cc_tupdesc,
943 : &isNull);
1418 tgl 944 1649787 : Assert(!isNull); /* columns used as oids should never be NULL */
8179 945 1649787 : ReleaseSysCache(tuple);
946 1649787 : 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
7555 959 125667 : SearchSysCacheAttName(Oid relid, const char *attname)
960 : {
961 : HeapTuple tuple;
962 :
4802 rhaas 963 125667 : tuple = SearchSysCache2(ATTNAME,
964 : ObjectIdGetDatum(relid),
965 : CStringGetDatum(attname));
7555 tgl 966 125667 : if (!HeapTupleIsValid(tuple))
967 413 : return NULL;
968 125254 : if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
969 : {
970 39 : ReleaseSysCache(tuple);
971 39 : return NULL;
972 : }
973 125215 : return tuple;
974 : }
975 :
976 : /*
977 : * SearchSysCacheCopyAttName
978 : *
979 : * As above, an attisdropped-aware version of SearchSysCacheCopy.
980 : */
981 : HeapTuple
982 4056 : SearchSysCacheCopyAttName(Oid relid, const char *attname)
983 : {
984 : HeapTuple tuple,
985 : newtuple;
986 :
987 4056 : tuple = SearchSysCacheAttName(relid, attname);
988 4056 : if (!HeapTupleIsValid(tuple))
989 318 : return tuple;
990 3738 : newtuple = heap_copytuple(tuple);
991 3738 : ReleaseSysCache(tuple);
992 3738 : return newtuple;
993 : }
994 :
995 : /*
996 : * SearchSysCacheExistsAttName
997 : *
998 : * As above, an attisdropped-aware version of SearchSysCacheExists.
999 : */
1000 : bool
1001 399 : SearchSysCacheExistsAttName(Oid relid, const char *attname)
1002 : {
1003 : HeapTuple tuple;
1004 :
1005 399 : tuple = SearchSysCacheAttName(relid, attname);
1006 399 : if (!HeapTupleIsValid(tuple))
1007 6 : return false;
1008 393 : ReleaseSysCache(tuple);
1009 393 : 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
2041 simon 1022 32403 : SearchSysCacheAttNum(Oid relid, int16 attnum)
1023 : {
1024 : HeapTuple tuple;
1025 :
1026 32403 : tuple = SearchSysCache2(ATTNUM,
1027 : ObjectIdGetDatum(relid),
1028 : Int16GetDatum(attnum));
1029 32403 : if (!HeapTupleIsValid(tuple))
1030 6 : return NULL;
1031 32397 : if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
1032 : {
2041 simon 1033 UIC 0 : ReleaseSysCache(tuple);
1034 0 : return NULL;
1035 : }
2041 simon 1036 GIC 32397 : return tuple;
1037 : }
1038 :
1039 : /*
1040 : * SearchSysCacheCopyAttNum
1041 : *
1042 : * As above, an attisdropped-aware version of SearchSysCacheCopy.
1043 : */
1044 : HeapTuple
1045 32403 : SearchSysCacheCopyAttNum(Oid relid, int16 attnum)
1046 : {
1047 : HeapTuple tuple,
1048 : newtuple;
1049 :
1050 32403 : tuple = SearchSysCacheAttNum(relid, attnum);
1051 32403 : if (!HeapTupleIsValid(tuple))
1052 6 : return NULL;
1053 32397 : newtuple = heap_copytuple(tuple);
1054 32397 : ReleaseSysCache(tuple);
1055 32397 : 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
8477 tgl 1079 2805963 : 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 : */
6029 1089 2805963 : if (cacheId < 0 || cacheId >= SysCacheSize ||
1090 2805963 : !PointerIsValid(SysCache[cacheId]))
4312 peter_e 1091 UIC 0 : elog(ERROR, "invalid cache ID: %d", cacheId);
6029 tgl 1092 GIC 2805963 : if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
1093 : {
1094 10693 : InitCatCachePhase2(SysCache[cacheId], false);
1095 10693 : Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
1096 : }
1097 :
8477 1098 5611926 : return heap_getattr(tup, attributeNumber,
1099 2805963 : 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
15 dgustafsson 1110 GNC 1490587 : SysCacheGetAttrNotNull(int cacheId, HeapTuple tup,
1111 : AttrNumber attributeNumber)
1112 : {
1113 : bool isnull;
1114 : Datum attr;
1115 :
1116 1490587 : attr = SysCacheGetAttr(cacheId, tup, attributeNumber, &isnull);
1117 :
1118 1490587 : if (isnull)
1119 : {
15 dgustafsson 1120 UNC 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 :
15 dgustafsson 1126 GNC 1490587 : 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
4050 tgl 1140 GIC 107685 : GetSysCacheHashValue(int cacheId,
1141 : Datum key1,
1142 : Datum key2,
1143 : Datum key3,
1144 : Datum key4)
1145 : {
1146 107685 : if (cacheId < 0 || cacheId >= SysCacheSize ||
1147 107685 : !PointerIsValid(SysCache[cacheId]))
4050 tgl 1148 UIC 0 : elog(ERROR, "invalid cache ID: %d", cacheId);
1149 :
4050 tgl 1150 GIC 107685 : return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
1151 : }
1152 :
1153 : /*
1154 : * List-search interface
1155 : */
1156 : struct catclist *
7673 1157 1597361 : SearchSysCacheList(int cacheId, int nkeys,
1158 : Datum key1, Datum key2, Datum key3)
1159 : {
1160 1597361 : if (cacheId < 0 || cacheId >= SysCacheSize ||
7522 bruce 1161 1597361 : !PointerIsValid(SysCache[cacheId]))
4312 peter_e 1162 UIC 0 : elog(ERROR, "invalid cache ID: %d", cacheId);
1163 :
7673 tgl 1164 GIC 1597361 : 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
2158 1177 14189254 : SysCacheInvalidate(int cacheId, uint32 hashValue)
1178 : {
1179 14189254 : if (cacheId < 0 || cacheId >= SysCacheSize)
2158 tgl 1180 UIC 0 : elog(ERROR, "invalid cache ID: %d", cacheId);
1181 :
1182 : /* if this cache isn't initialized yet, no need to do anything */
2158 tgl 1183 GIC 14189254 : if (!PointerIsValid(SysCache[cacheId]))
2158 tgl 1184 UIC 0 : return;
1185 :
2158 tgl 1186 GIC 14189254 : 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
3568 rhaas 1201 12013240 : RelationInvalidatesSnapshotsOnly(Oid relid)
1202 : {
1203 12013240 : switch (relid)
1204 : {
1205 2049989 : case DbRoleSettingRelationId:
1206 : case DependRelationId:
1207 : case SharedDependRelationId:
1208 : case DescriptionRelationId:
1209 : case SharedDescriptionRelationId:
1210 : case SecLabelRelationId:
1211 : case SharedSecLabelRelationId:
1212 2049989 : return true;
1213 9963251 : default:
1214 9963251 : break;
1215 : }
1216 :
1217 9963251 : return false;
1218 : }
1219 :
1220 : /*
1221 : * Test whether a relation has a system cache.
1222 : */
1223 : bool
1224 6267904 : RelationHasSysCache(Oid relid)
1225 : {
3260 bruce 1226 6267904 : int low = 0,
1227 6267904 : high = SysCacheRelationOidSize - 1;
1228 :
3568 rhaas 1229 28147230 : while (low <= high)
1230 : {
3260 bruce 1231 27957782 : int middle = low + (high - low) / 2;
1232 :
3568 rhaas 1233 27957782 : if (SysCacheRelationOid[middle] == relid)
1234 6078456 : return true;
1235 21879326 : if (SysCacheRelationOid[middle] < relid)
1236 8052803 : low = middle + 1;
1237 : else
1238 13826523 : high = middle - 1;
1239 : }
1240 :
1241 189448 : 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
2863 tgl 1249 1566112 : RelationSupportsSysCache(Oid relid)
1250 : {
1251 1566112 : int low = 0,
1252 1566112 : high = SysCacheSupportingRelOidSize - 1;
1253 :
1254 13257348 : while (low <= high)
1255 : {
1256 11957482 : int middle = low + (high - low) / 2;
1257 :
1258 11957482 : if (SysCacheSupportingRelOid[middle] == relid)
1259 266246 : return true;
1260 11691236 : if (SysCacheSupportingRelOid[middle] < relid)
1261 10786852 : low = middle + 1;
1262 : else
1263 904384 : high = middle - 1;
1264 : }
1265 :
1266 1299866 : return false;
1267 : }
1268 :
1269 :
1270 : /*
1271 : * OID comparator for pg_qsort
1272 : */
1273 : static int
3568 rhaas 1274 21959860 : oid_compare(const void *a, const void *b)
1275 : {
2863 tgl 1276 21959860 : Oid oa = *((const Oid *) a);
1277 21959860 : Oid ob = *((const Oid *) b);
1278 :
3568 rhaas 1279 21959860 : if (oa == ob)
1280 1862770 : return 0;
1281 20097090 : return (oa > ob) ? 1 : -1;
1282 : }
|