]> granicus.if.org Git - postgresql/blob - src/backend/utils/cache/syscache.c
Per-column collation support
[postgresql] / src / backend / utils / cache / syscache.c
1 /*-------------------------------------------------------------------------
2  *
3  * syscache.c
4  *        System cache management routines
5  *
6  * Portions Copyright (c) 1996-2011, 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 id's
18  *
19  *-------------------------------------------------------------------------
20  */
21 #include "postgres.h"
22
23 #include "access/sysattr.h"
24 #include "catalog/indexing.h"
25 #include "catalog/pg_aggregate.h"
26 #include "catalog/pg_amop.h"
27 #include "catalog/pg_amproc.h"
28 #include "catalog/pg_auth_members.h"
29 #include "catalog/pg_authid.h"
30 #include "catalog/pg_cast.h"
31 #include "catalog/pg_collation.h"
32 #include "catalog/pg_constraint.h"
33 #include "catalog/pg_conversion.h"
34 #include "catalog/pg_database.h"
35 #include "catalog/pg_default_acl.h"
36 #include "catalog/pg_enum.h"
37 #include "catalog/pg_foreign_data_wrapper.h"
38 #include "catalog/pg_foreign_server.h"
39 #include "catalog/pg_foreign_table.h"
40 #include "catalog/pg_language.h"
41 #include "catalog/pg_namespace.h"
42 #include "catalog/pg_opclass.h"
43 #include "catalog/pg_operator.h"
44 #include "catalog/pg_opfamily.h"
45 #include "catalog/pg_proc.h"
46 #include "catalog/pg_rewrite.h"
47 #include "catalog/pg_statistic.h"
48 #include "catalog/pg_tablespace.h"
49 #include "catalog/pg_ts_config.h"
50 #include "catalog/pg_ts_config_map.h"
51 #include "catalog/pg_ts_dict.h"
52 #include "catalog/pg_ts_parser.h"
53 #include "catalog/pg_ts_template.h"
54 #include "catalog/pg_type.h"
55 #include "catalog/pg_user_mapping.h"
56 #include "utils/rel.h"
57 #include "utils/syscache.h"
58
59
60 /*---------------------------------------------------------------------------
61
62         Adding system caches:
63
64         Add your new cache to the list in include/utils/syscache.h.
65         Keep the list sorted alphabetically.
66
67         Add your entry to the cacheinfo[] array below. All cache lists are
68         alphabetical, so add it in the proper place.  Specify the relation OID,
69         index OID, number of keys, key attribute numbers, and initial number of
70         hash buckets.
71
72         The number of hash buckets must be a power of 2.  It's reasonable to
73         set this to the number of entries that might be in the particular cache
74         in a medium-size database.
75
76         There must be a unique index underlying each syscache (ie, an index
77         whose key is the same as that of the cache).  If there is not one
78         already, add definitions for it to include/catalog/indexing.h: you need
79         to add a DECLARE_UNIQUE_INDEX macro and a #define for the index OID.
80         (Adding an index requires a catversion.h update, while simply
81         adding/deleting caches only requires a recompile.)
82
83         Finally, any place your relation gets heap_insert() or
84         heap_update() calls, make sure there is a CatalogUpdateIndexes() or
85         similar call.  The heap_* calls do not update indexes.
86
87         bjm 1999/11/22
88
89 *---------------------------------------------------------------------------
90 */
91
92 /*
93  *              struct cachedesc: information defining a single syscache
94  */
95 struct cachedesc
96 {
97         Oid                     reloid;                 /* OID of the relation being cached */
98         Oid                     indoid;                 /* OID of index relation for this cache */
99         int                     nkeys;                  /* # of keys needed for cache lookup */
100         int                     key[4];                 /* attribute numbers of key attrs */
101         int                     nbuckets;               /* number of hash buckets for this cache */
102 };
103
104 static const struct cachedesc cacheinfo[] = {
105         {AggregateRelationId,           /* AGGFNOID */
106                 AggregateFnoidIndexId,
107                 1,
108                 {
109                         Anum_pg_aggregate_aggfnoid,
110                         0,
111                         0,
112                         0
113                 },
114                 32
115         },
116         {AccessMethodRelationId,        /* AMNAME */
117                 AmNameIndexId,
118                 1,
119                 {
120                         Anum_pg_am_amname,
121                         0,
122                         0,
123                         0
124                 },
125                 4
126         },
127         {AccessMethodRelationId,        /* AMOID */
128                 AmOidIndexId,
129                 1,
130                 {
131                         ObjectIdAttributeNumber,
132                         0,
133                         0,
134                         0
135                 },
136                 4
137         },
138         {AccessMethodOperatorRelationId,        /* AMOPOPID */
139                 AccessMethodOperatorIndexId,
140                 3,
141                 {
142                         Anum_pg_amop_amopopr,
143                         Anum_pg_amop_amoppurpose,
144                         Anum_pg_amop_amopfamily,
145                         0
146                 },
147                 64
148         },
149         {AccessMethodOperatorRelationId,        /* AMOPSTRATEGY */
150                 AccessMethodStrategyIndexId,
151                 4,
152                 {
153                         Anum_pg_amop_amopfamily,
154                         Anum_pg_amop_amoplefttype,
155                         Anum_pg_amop_amoprighttype,
156                         Anum_pg_amop_amopstrategy
157                 },
158                 64
159         },
160         {AccessMethodProcedureRelationId,       /* AMPROCNUM */
161                 AccessMethodProcedureIndexId,
162                 4,
163                 {
164                         Anum_pg_amproc_amprocfamily,
165                         Anum_pg_amproc_amproclefttype,
166                         Anum_pg_amproc_amprocrighttype,
167                         Anum_pg_amproc_amprocnum
168                 },
169                 64
170         },
171         {AttributeRelationId,           /* ATTNAME */
172                 AttributeRelidNameIndexId,
173                 2,
174                 {
175                         Anum_pg_attribute_attrelid,
176                         Anum_pg_attribute_attname,
177                         0,
178                         0
179                 },
180                 2048
181         },
182         {AttributeRelationId,           /* ATTNUM */
183                 AttributeRelidNumIndexId,
184                 2,
185                 {
186                         Anum_pg_attribute_attrelid,
187                         Anum_pg_attribute_attnum,
188                         0,
189                         0
190                 },
191                 2048
192         },
193         {AuthMemRelationId,                     /* AUTHMEMMEMROLE */
194                 AuthMemMemRoleIndexId,
195                 2,
196                 {
197                         Anum_pg_auth_members_member,
198                         Anum_pg_auth_members_roleid,
199                         0,
200                         0
201                 },
202                 128
203         },
204         {AuthMemRelationId,                     /* AUTHMEMROLEMEM */
205                 AuthMemRoleMemIndexId,
206                 2,
207                 {
208                         Anum_pg_auth_members_roleid,
209                         Anum_pg_auth_members_member,
210                         0,
211                         0
212                 },
213                 128
214         },
215         {AuthIdRelationId,                      /* AUTHNAME */
216                 AuthIdRolnameIndexId,
217                 1,
218                 {
219                         Anum_pg_authid_rolname,
220                         0,
221                         0,
222                         0
223                 },
224                 128
225         },
226         {AuthIdRelationId,                      /* AUTHOID */
227                 AuthIdOidIndexId,
228                 1,
229                 {
230                         ObjectIdAttributeNumber,
231                         0,
232                         0,
233                         0
234                 },
235                 128
236         },
237         {
238                 CastRelationId,                 /* CASTSOURCETARGET */
239                 CastSourceTargetIndexId,
240                 2,
241                 {
242                         Anum_pg_cast_castsource,
243                         Anum_pg_cast_casttarget,
244                         0,
245                         0
246                 },
247                 256
248         },
249         {OperatorClassRelationId,       /* CLAAMNAMENSP */
250                 OpclassAmNameNspIndexId,
251                 3,
252                 {
253                         Anum_pg_opclass_opcmethod,
254                         Anum_pg_opclass_opcname,
255                         Anum_pg_opclass_opcnamespace,
256                         0
257                 },
258                 64
259         },
260         {OperatorClassRelationId,       /* CLAOID */
261                 OpclassOidIndexId,
262                 1,
263                 {
264                         ObjectIdAttributeNumber,
265                         0,
266                         0,
267                         0
268                 },
269                 64
270         },
271         {CollationRelationId,           /* COLLNAMEENCNSP */
272                 CollationNameEncNspIndexId,
273                 3,
274                 {
275                         Anum_pg_collation_collname,
276                         Anum_pg_collation_collencoding,
277                         Anum_pg_collation_collnamespace,
278                         0
279                 },
280                 256
281         },
282         {CollationRelationId,           /* COLLOID */
283                 CollationOidIndexId,
284                 1,
285                 {
286                         ObjectIdAttributeNumber,
287                         0,
288                         0,
289                         0
290                 },
291                 256
292         },
293         {ConversionRelationId,          /* CONDEFAULT */
294                 ConversionDefaultIndexId,
295                 4,
296                 {
297                         Anum_pg_conversion_connamespace,
298                         Anum_pg_conversion_conforencoding,
299                         Anum_pg_conversion_contoencoding,
300                         ObjectIdAttributeNumber,
301                 },
302                 128
303         },
304         {ConversionRelationId,          /* CONNAMENSP */
305                 ConversionNameNspIndexId,
306                 2,
307                 {
308                         Anum_pg_conversion_conname,
309                         Anum_pg_conversion_connamespace,
310                         0,
311                         0
312                 },
313                 128
314         },
315         {ConstraintRelationId,          /* CONSTROID */
316                 ConstraintOidIndexId,
317                 1,
318                 {
319                         ObjectIdAttributeNumber,
320                         0,
321                         0,
322                         0
323                 },
324                 1024
325         },
326         {ConversionRelationId,          /* CONVOID */
327                 ConversionOidIndexId,
328                 1,
329                 {
330                         ObjectIdAttributeNumber,
331                         0,
332                         0,
333                         0
334                 },
335                 128
336         },
337         {DatabaseRelationId,            /* DATABASEOID */
338                 DatabaseOidIndexId,
339                 1,
340                 {
341                         ObjectIdAttributeNumber,
342                         0,
343                         0,
344                         0
345                 },
346                 4
347         },
348         {DefaultAclRelationId,          /* DEFACLROLENSPOBJ */
349                 DefaultAclRoleNspObjIndexId,
350                 3,
351                 {
352                         Anum_pg_default_acl_defaclrole,
353                         Anum_pg_default_acl_defaclnamespace,
354                         Anum_pg_default_acl_defaclobjtype,
355                         0
356                 },
357                 256
358         },
359         {EnumRelationId,                        /* ENUMOID */
360                 EnumOidIndexId,
361                 1,
362                 {
363                         ObjectIdAttributeNumber,
364                         0,
365                         0,
366                         0
367                 },
368                 256
369         },
370         {EnumRelationId,                        /* ENUMTYPOIDNAME */
371                 EnumTypIdLabelIndexId,
372                 2,
373                 {
374                         Anum_pg_enum_enumtypid,
375                         Anum_pg_enum_enumlabel,
376                         0,
377                         0
378                 },
379                 256
380         },
381         {ForeignDataWrapperRelationId,          /* FOREIGNDATAWRAPPERNAME */
382                 ForeignDataWrapperNameIndexId,
383                 1,
384                 {
385                         Anum_pg_foreign_data_wrapper_fdwname,
386                         0,
387                         0,
388                         0
389                 },
390                 8
391         },
392         {ForeignDataWrapperRelationId,          /* FOREIGNDATAWRAPPEROID */
393                 ForeignDataWrapperOidIndexId,
394                 1,
395                 {
396                         ObjectIdAttributeNumber,
397                         0,
398                         0,
399                         0
400                 },
401                 8
402         },
403         {ForeignServerRelationId,       /* FOREIGNSERVERNAME */
404                 ForeignServerNameIndexId,
405                 1,
406                 {
407                         Anum_pg_foreign_server_srvname,
408                         0,
409                         0,
410                         0
411                 },
412                 32
413         },
414         {ForeignServerRelationId,       /* FOREIGNSERVEROID */
415                 ForeignServerOidIndexId,
416                 1,
417                 {
418                         ObjectIdAttributeNumber,
419                         0,
420                         0,
421                         0
422                 },
423                 32
424         },
425         {ForeignTableRelationId,                /* FOREIGNTABLEREL */
426                 ForeignTableRelidIndexId,
427                 1,
428                 {
429                         Anum_pg_foreign_table_ftrelid,
430                         0,
431                         0,
432                         0
433                 },
434                 128
435         },
436         {IndexRelationId,                       /* INDEXRELID */
437                 IndexRelidIndexId,
438                 1,
439                 {
440                         Anum_pg_index_indexrelid,
441                         0,
442                         0,
443                         0
444                 },
445                 1024
446         },
447         {LanguageRelationId,            /* LANGNAME */
448                 LanguageNameIndexId,
449                 1,
450                 {
451                         Anum_pg_language_lanname,
452                         0,
453                         0,
454                         0
455                 },
456                 4
457         },
458         {LanguageRelationId,            /* LANGOID */
459                 LanguageOidIndexId,
460                 1,
461                 {
462                         ObjectIdAttributeNumber,
463                         0,
464                         0,
465                         0
466                 },
467                 4
468         },
469         {NamespaceRelationId,           /* NAMESPACENAME */
470                 NamespaceNameIndexId,
471                 1,
472                 {
473                         Anum_pg_namespace_nspname,
474                         0,
475                         0,
476                         0
477                 },
478                 256
479         },
480         {NamespaceRelationId,           /* NAMESPACEOID */
481                 NamespaceOidIndexId,
482                 1,
483                 {
484                         ObjectIdAttributeNumber,
485                         0,
486                         0,
487                         0
488                 },
489                 256
490         },
491         {OperatorRelationId,            /* OPERNAMENSP */
492                 OperatorNameNspIndexId,
493                 4,
494                 {
495                         Anum_pg_operator_oprname,
496                         Anum_pg_operator_oprleft,
497                         Anum_pg_operator_oprright,
498                         Anum_pg_operator_oprnamespace
499                 },
500                 1024
501         },
502         {OperatorRelationId,            /* OPEROID */
503                 OperatorOidIndexId,
504                 1,
505                 {
506                         ObjectIdAttributeNumber,
507                         0,
508                         0,
509                         0
510                 },
511                 1024
512         },
513         {OperatorFamilyRelationId,      /* OPFAMILYAMNAMENSP */
514                 OpfamilyAmNameNspIndexId,
515                 3,
516                 {
517                         Anum_pg_opfamily_opfmethod,
518                         Anum_pg_opfamily_opfname,
519                         Anum_pg_opfamily_opfnamespace,
520                         0
521                 },
522                 64
523         },
524         {OperatorFamilyRelationId,      /* OPFAMILYOID */
525                 OpfamilyOidIndexId,
526                 1,
527                 {
528                         ObjectIdAttributeNumber,
529                         0,
530                         0,
531                         0
532                 },
533                 64
534         },
535         {ProcedureRelationId,           /* PROCNAMEARGSNSP */
536                 ProcedureNameArgsNspIndexId,
537                 3,
538                 {
539                         Anum_pg_proc_proname,
540                         Anum_pg_proc_proargtypes,
541                         Anum_pg_proc_pronamespace,
542                         0
543                 },
544                 2048
545         },
546         {ProcedureRelationId,           /* PROCOID */
547                 ProcedureOidIndexId,
548                 1,
549                 {
550                         ObjectIdAttributeNumber,
551                         0,
552                         0,
553                         0
554                 },
555                 2048
556         },
557         {RelationRelationId,            /* RELNAMENSP */
558                 ClassNameNspIndexId,
559                 2,
560                 {
561                         Anum_pg_class_relname,
562                         Anum_pg_class_relnamespace,
563                         0,
564                         0
565                 },
566                 1024
567         },
568         {RelationRelationId,            /* RELOID */
569                 ClassOidIndexId,
570                 1,
571                 {
572                         ObjectIdAttributeNumber,
573                         0,
574                         0,
575                         0
576                 },
577                 1024
578         },
579         {RewriteRelationId,                     /* RULERELNAME */
580                 RewriteRelRulenameIndexId,
581                 2,
582                 {
583                         Anum_pg_rewrite_ev_class,
584                         Anum_pg_rewrite_rulename,
585                         0,
586                         0
587                 },
588                 1024
589         },
590         {StatisticRelationId,           /* STATRELATTINH */
591                 StatisticRelidAttnumInhIndexId,
592                 3,
593                 {
594                         Anum_pg_statistic_starelid,
595                         Anum_pg_statistic_staattnum,
596                         Anum_pg_statistic_stainherit,
597                         0
598                 },
599                 1024
600         },
601         {TableSpaceRelationId,          /* TABLESPACEOID */
602                 TablespaceOidIndexId,
603                 1,
604                 {
605                         ObjectIdAttributeNumber,
606                         0,
607                         0,
608                         0,
609                 },
610                 16
611         },
612         {TSConfigMapRelationId,         /* TSCONFIGMAP */
613                 TSConfigMapIndexId,
614                 3,
615                 {
616                         Anum_pg_ts_config_map_mapcfg,
617                         Anum_pg_ts_config_map_maptokentype,
618                         Anum_pg_ts_config_map_mapseqno,
619                         0
620                 },
621                 4
622         },
623         {TSConfigRelationId,            /* TSCONFIGNAMENSP */
624                 TSConfigNameNspIndexId,
625                 2,
626                 {
627                         Anum_pg_ts_config_cfgname,
628                         Anum_pg_ts_config_cfgnamespace,
629                         0,
630                         0
631                 },
632                 16
633         },
634         {TSConfigRelationId,            /* TSCONFIGOID */
635                 TSConfigOidIndexId,
636                 1,
637                 {
638                         ObjectIdAttributeNumber,
639                         0,
640                         0,
641                         0
642                 },
643                 16
644         },
645         {TSDictionaryRelationId,        /* TSDICTNAMENSP */
646                 TSDictionaryNameNspIndexId,
647                 2,
648                 {
649                         Anum_pg_ts_dict_dictname,
650                         Anum_pg_ts_dict_dictnamespace,
651                         0,
652                         0
653                 },
654                 16
655         },
656         {TSDictionaryRelationId,        /* TSDICTOID */
657                 TSDictionaryOidIndexId,
658                 1,
659                 {
660                         ObjectIdAttributeNumber,
661                         0,
662                         0,
663                         0
664                 },
665                 16
666         },
667         {TSParserRelationId,            /* TSPARSERNAMENSP */
668                 TSParserNameNspIndexId,
669                 2,
670                 {
671                         Anum_pg_ts_parser_prsname,
672                         Anum_pg_ts_parser_prsnamespace,
673                         0,
674                         0
675                 },
676                 4
677         },
678         {TSParserRelationId,            /* TSPARSEROID */
679                 TSParserOidIndexId,
680                 1,
681                 {
682                         ObjectIdAttributeNumber,
683                         0,
684                         0,
685                         0
686                 },
687                 4
688         },
689         {TSTemplateRelationId,          /* TSTEMPLATENAMENSP */
690                 TSTemplateNameNspIndexId,
691                 2,
692                 {
693                         Anum_pg_ts_template_tmplname,
694                         Anum_pg_ts_template_tmplnamespace,
695                         0,
696                         0
697                 },
698                 16
699         },
700         {TSTemplateRelationId,          /* TSTEMPLATEOID */
701                 TSTemplateOidIndexId,
702                 1,
703                 {
704                         ObjectIdAttributeNumber,
705                         0,
706                         0,
707                         0
708                 },
709                 16
710         },
711         {TypeRelationId,                        /* TYPENAMENSP */
712                 TypeNameNspIndexId,
713                 2,
714                 {
715                         Anum_pg_type_typname,
716                         Anum_pg_type_typnamespace,
717                         0,
718                         0
719                 },
720                 1024
721         },
722         {TypeRelationId,                        /* TYPEOID */
723                 TypeOidIndexId,
724                 1,
725                 {
726                         ObjectIdAttributeNumber,
727                         0,
728                         0,
729                         0
730                 },
731                 1024
732         },
733         {UserMappingRelationId,         /* USERMAPPINGOID */
734                 UserMappingOidIndexId,
735                 1,
736                 {
737                         ObjectIdAttributeNumber,
738                         0,
739                         0,
740                         0
741                 },
742                 128
743         },
744         {UserMappingRelationId,         /* USERMAPPINGUSERSERVER */
745                 UserMappingUserServerIndexId,
746                 2,
747                 {
748                         Anum_pg_user_mapping_umuser,
749                         Anum_pg_user_mapping_umserver,
750                         0,
751                         0
752                 },
753                 128
754         }
755 };
756
757 static CatCache *SysCache[
758                                                   lengthof(cacheinfo)];
759 static int      SysCacheSize = lengthof(cacheinfo);
760 static bool CacheInitialized = false;
761
762
763 /*
764  * InitCatalogCache - initialize the caches
765  *
766  * Note that no database access is done here; we only allocate memory
767  * and initialize the cache structure.  Interrogation of the database
768  * to complete initialization of a cache happens upon first use
769  * of that cache.
770  */
771 void
772 InitCatalogCache(void)
773 {
774         int                     cacheId;
775
776         Assert(!CacheInitialized);
777
778         MemSet(SysCache, 0, sizeof(SysCache));
779
780         for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
781         {
782                 SysCache[cacheId] = InitCatCache(cacheId,
783                                                                                  cacheinfo[cacheId].reloid,
784                                                                                  cacheinfo[cacheId].indoid,
785                                                                                  cacheinfo[cacheId].nkeys,
786                                                                                  cacheinfo[cacheId].key,
787                                                                                  cacheinfo[cacheId].nbuckets);
788                 if (!PointerIsValid(SysCache[cacheId]))
789                         elog(ERROR, "could not initialize cache %u (%d)",
790                                  cacheinfo[cacheId].reloid, cacheId);
791         }
792         CacheInitialized = true;
793 }
794
795
796 /*
797  * InitCatalogCachePhase2 - finish initializing the caches
798  *
799  * Finish initializing all the caches, including necessary database
800  * access.
801  *
802  * This is *not* essential; normally we allow syscaches to be initialized
803  * on first use.  However, it is useful as a mechanism to preload the
804  * relcache with entries for the most-commonly-used system catalogs.
805  * Therefore, we invoke this routine when we need to write a new relcache
806  * init file.
807  */
808 void
809 InitCatalogCachePhase2(void)
810 {
811         int                     cacheId;
812
813         Assert(CacheInitialized);
814
815         for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
816                 InitCatCachePhase2(SysCache[cacheId], true);
817 }
818
819
820 /*
821  * SearchSysCache
822  *
823  *      A layer on top of SearchCatCache that does the initialization and
824  *      key-setting for you.
825  *
826  *      Returns the cache copy of the tuple if one is found, NULL if not.
827  *      The tuple is the 'cache' copy and must NOT be modified!
828  *
829  *      When the caller is done using the tuple, call ReleaseSysCache()
830  *      to release the reference count grabbed by SearchSysCache().  If this
831  *      is not done, the tuple will remain locked in cache until end of
832  *      transaction, which is tolerable but not desirable.
833  *
834  *      CAUTION: The tuple that is returned must NOT be freed by the caller!
835  */
836 HeapTuple
837 SearchSysCache(int cacheId,
838                            Datum key1,
839                            Datum key2,
840                            Datum key3,
841                            Datum key4)
842 {
843         if (cacheId < 0 || cacheId >= SysCacheSize ||
844                 !PointerIsValid(SysCache[cacheId]))
845                 elog(ERROR, "invalid cache id: %d", cacheId);
846
847         return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
848 }
849
850 /*
851  * ReleaseSysCache
852  *              Release previously grabbed reference count on a tuple
853  */
854 void
855 ReleaseSysCache(HeapTuple tuple)
856 {
857         ReleaseCatCache(tuple);
858 }
859
860 /*
861  * SearchSysCacheCopy
862  *
863  * A convenience routine that does SearchSysCache and (if successful)
864  * returns a modifiable copy of the syscache entry.  The original
865  * syscache entry is released before returning.  The caller should
866  * heap_freetuple() the result when done with it.
867  */
868 HeapTuple
869 SearchSysCacheCopy(int cacheId,
870                                    Datum key1,
871                                    Datum key2,
872                                    Datum key3,
873                                    Datum key4)
874 {
875         HeapTuple       tuple,
876                                 newtuple;
877
878         tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
879         if (!HeapTupleIsValid(tuple))
880                 return tuple;
881         newtuple = heap_copytuple(tuple);
882         ReleaseSysCache(tuple);
883         return newtuple;
884 }
885
886 /*
887  * SearchSysCacheExists
888  *
889  * A convenience routine that just probes to see if a tuple can be found.
890  * No lock is retained on the syscache entry.
891  */
892 bool
893 SearchSysCacheExists(int cacheId,
894                                          Datum key1,
895                                          Datum key2,
896                                          Datum key3,
897                                          Datum key4)
898 {
899         HeapTuple       tuple;
900
901         tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
902         if (!HeapTupleIsValid(tuple))
903                 return false;
904         ReleaseSysCache(tuple);
905         return true;
906 }
907
908 /*
909  * GetSysCacheOid
910  *
911  * A convenience routine that does SearchSysCache and returns the OID
912  * of the found tuple, or InvalidOid if no tuple could be found.
913  * No lock is retained on the syscache entry.
914  */
915 Oid
916 GetSysCacheOid(int cacheId,
917                            Datum key1,
918                            Datum key2,
919                            Datum key3,
920                            Datum key4)
921 {
922         HeapTuple       tuple;
923         Oid                     result;
924
925         tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
926         if (!HeapTupleIsValid(tuple))
927                 return InvalidOid;
928         result = HeapTupleGetOid(tuple);
929         ReleaseSysCache(tuple);
930         return result;
931 }
932
933
934 /*
935  * SearchSysCacheAttName
936  *
937  * This routine is equivalent to SearchSysCache on the ATTNAME cache,
938  * except that it will return NULL if the found attribute is marked
939  * attisdropped.  This is convenient for callers that want to act as
940  * though dropped attributes don't exist.
941  */
942 HeapTuple
943 SearchSysCacheAttName(Oid relid, const char *attname)
944 {
945         HeapTuple       tuple;
946
947         tuple = SearchSysCache2(ATTNAME,
948                                                         ObjectIdGetDatum(relid),
949                                                         CStringGetDatum(attname));
950         if (!HeapTupleIsValid(tuple))
951                 return NULL;
952         if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
953         {
954                 ReleaseSysCache(tuple);
955                 return NULL;
956         }
957         return tuple;
958 }
959
960 /*
961  * SearchSysCacheCopyAttName
962  *
963  * As above, an attisdropped-aware version of SearchSysCacheCopy.
964  */
965 HeapTuple
966 SearchSysCacheCopyAttName(Oid relid, const char *attname)
967 {
968         HeapTuple       tuple,
969                                 newtuple;
970
971         tuple = SearchSysCacheAttName(relid, attname);
972         if (!HeapTupleIsValid(tuple))
973                 return tuple;
974         newtuple = heap_copytuple(tuple);
975         ReleaseSysCache(tuple);
976         return newtuple;
977 }
978
979 /*
980  * SearchSysCacheExistsAttName
981  *
982  * As above, an attisdropped-aware version of SearchSysCacheExists.
983  */
984 bool
985 SearchSysCacheExistsAttName(Oid relid, const char *attname)
986 {
987         HeapTuple       tuple;
988
989         tuple = SearchSysCacheAttName(relid, attname);
990         if (!HeapTupleIsValid(tuple))
991                 return false;
992         ReleaseSysCache(tuple);
993         return true;
994 }
995
996
997 /*
998  * SysCacheGetAttr
999  *
1000  *              Given a tuple previously fetched by SearchSysCache(),
1001  *              extract a specific attribute.
1002  *
1003  * This is equivalent to using heap_getattr() on a tuple fetched
1004  * from a non-cached relation.  Usually, this is only used for attributes
1005  * that could be NULL or variable length; the fixed-size attributes in
1006  * a system table are accessed just by mapping the tuple onto the C struct
1007  * declarations from include/catalog/.
1008  *
1009  * As with heap_getattr(), if the attribute is of a pass-by-reference type
1010  * then a pointer into the tuple data area is returned --- the caller must
1011  * not modify or pfree the datum!
1012  *
1013  * Note: it is legal to use SysCacheGetAttr() with a cacheId referencing
1014  * a different cache for the same catalog the tuple was fetched from.
1015  */
1016 Datum
1017 SysCacheGetAttr(int cacheId, HeapTuple tup,
1018                                 AttrNumber attributeNumber,
1019                                 bool *isNull)
1020 {
1021         /*
1022          * We just need to get the TupleDesc out of the cache entry, and then we
1023          * can apply heap_getattr().  Normally the cache control data is already
1024          * valid (because the caller recently fetched the tuple via this same
1025          * cache), but there are cases where we have to initialize the cache here.
1026          */
1027         if (cacheId < 0 || cacheId >= SysCacheSize ||
1028                 !PointerIsValid(SysCache[cacheId]))
1029                 elog(ERROR, "invalid cache id: %d", cacheId);
1030         if (!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
1031         {
1032                 InitCatCachePhase2(SysCache[cacheId], false);
1033                 Assert(PointerIsValid(SysCache[cacheId]->cc_tupdesc));
1034         }
1035
1036         return heap_getattr(tup, attributeNumber,
1037                                                 SysCache[cacheId]->cc_tupdesc,
1038                                                 isNull);
1039 }
1040
1041 /*
1042  * List-search interface
1043  */
1044 struct catclist *
1045 SearchSysCacheList(int cacheId, int nkeys,
1046                                    Datum key1, Datum key2, Datum key3, Datum key4)
1047 {
1048         if (cacheId < 0 || cacheId >= SysCacheSize ||
1049                 !PointerIsValid(SysCache[cacheId]))
1050                 elog(ERROR, "invalid cache id: %d", cacheId);
1051
1052         return SearchCatCacheList(SysCache[cacheId], nkeys,
1053                                                           key1, key2, key3, key4);
1054 }