1
/*-------------------------------------------------------------------------
4
* System cache management routines
6
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
7
* Portions Copyright (c) 1994, Regents of the University of California
11
* $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.96 2004-12-31 22:01:25 pgsql Exp $
14
* These routines allow the parser/planner/executor to perform
15
* rapid lookups on the contents of the system catalogs.
17
* see catalog/syscache.h for a list of the cache id's
19
*-------------------------------------------------------------------------
23
#include "access/heapam.h"
24
#include "access/transam.h"
25
#include "utils/builtins.h"
26
#include "catalog/catname.h"
27
#include "catalog/indexing.h"
28
#include "catalog/pg_aggregate.h"
29
#include "catalog/pg_amop.h"
30
#include "catalog/pg_amproc.h"
31
#include "catalog/pg_cast.h"
32
#include "catalog/pg_conversion.h"
33
#include "catalog/pg_group.h"
34
#include "catalog/pg_index.h"
35
#include "catalog/pg_inherits.h"
36
#include "catalog/pg_language.h"
37
#include "catalog/pg_namespace.h"
38
#include "catalog/pg_opclass.h"
39
#include "catalog/pg_operator.h"
40
#include "catalog/pg_proc.h"
41
#include "catalog/pg_rewrite.h"
42
#include "catalog/pg_shadow.h"
43
#include "catalog/pg_statistic.h"
44
#include "catalog/pg_type.h"
45
#include "utils/catcache.h"
46
#include "utils/syscache.h"
47
#include "miscadmin.h"
50
/*---------------------------------------------------------------------------
54
Add your new cache to the list in include/utils/syscache.h. Keep
55
the list sorted alphabetically and adjust the cache numbers
58
Add your entry to the cacheinfo[] array below. All cache lists are
59
alphabetical, so add it in the proper place. Specify the relation
60
name, index name, number of keys, and key attribute numbers. If the
61
relation contains tuples that are associated with a particular relation
62
(for example, its attributes, rules, triggers, etc) then specify the
63
attribute number that contains the OID of the associated relation.
64
This is used by CatalogCacheFlushRelation() to remove the correct
65
tuples during a table drop or relcache invalidation event.
67
There must be a unique index underlying each syscache (ie, an index
68
whose key is the same as that of the cache). If there is not one
69
already, add definitions for it to include/catalog/indexing.h: you
70
need a #define for the index name and a DECLARE_UNIQUE_INDEX macro
71
with the actual declaration. (This will require a catversion.h update,
72
while simply adding/deleting caches only requires a recompile.)
74
Finally, any place your relation gets heap_insert() or
75
heap_update calls, make sure there is a CatalogUpdateIndexes() or
76
similar call. The heap_* calls do not update indexes.
80
---------------------------------------------------------------------------
84
* struct cachedesc: information defining a single syscache
88
const char *name; /* name of the relation being cached */
89
const char *indname; /* name of index relation for this cache */
90
int reloidattr; /* attr number of rel OID reference, or 0 */
91
int nkeys; /* # of keys needed for cache lookup */
92
int key[4]; /* attribute numbers of key attrs */
95
static const struct cachedesc cacheinfo[] = {
96
{AggregateRelationName, /* AGGFNOID */
101
Anum_pg_aggregate_aggfnoid,
106
{AccessMethodRelationName, /* AMNAME */
116
{AccessMethodRelationName, /* AMOID */
121
ObjectIdAttributeNumber,
126
{AccessMethodOperatorRelationName, /* AMOPOPID */
127
AccessMethodOperatorIndex,
131
Anum_pg_amop_amopopr,
132
Anum_pg_amop_amopclaid,
136
{AccessMethodOperatorRelationName, /* AMOPSTRATEGY */
137
AccessMethodStrategyIndex,
141
Anum_pg_amop_amopclaid,
142
Anum_pg_amop_amopsubtype,
143
Anum_pg_amop_amopstrategy,
146
{AccessMethodProcedureRelationName, /* AMPROCNUM */
147
AccessMethodProcedureIndex,
151
Anum_pg_amproc_amopclaid,
152
Anum_pg_amproc_amprocsubtype,
153
Anum_pg_amproc_amprocnum,
156
{AttributeRelationName, /* ATTNAME */
157
AttributeRelidNameIndex,
158
Anum_pg_attribute_attrelid,
161
Anum_pg_attribute_attrelid,
162
Anum_pg_attribute_attname,
166
{AttributeRelationName, /* ATTNUM */
167
AttributeRelidNumIndex,
168
Anum_pg_attribute_attrelid,
171
Anum_pg_attribute_attrelid,
172
Anum_pg_attribute_attnum,
177
CastRelationName, /* CASTSOURCETARGET */
178
CastSourceTargetIndex,
182
Anum_pg_cast_castsource,
183
Anum_pg_cast_casttarget,
187
{OperatorClassRelationName, /* CLAAMNAMENSP */
188
OpclassAmNameNspIndex,
192
Anum_pg_opclass_opcamid,
193
Anum_pg_opclass_opcname,
194
Anum_pg_opclass_opcnamespace,
197
{OperatorClassRelationName, /* CLAOID */
202
ObjectIdAttributeNumber,
207
{ConversionRelationName, /* CONDEFAULT */
208
ConversionDefaultIndex,
212
Anum_pg_conversion_connamespace,
213
Anum_pg_conversion_conforencoding,
214
Anum_pg_conversion_contoencoding,
215
ObjectIdAttributeNumber,
217
{ConversionRelationName, /* CONNAMENSP */
218
ConversionNameNspIndex,
222
Anum_pg_conversion_conname,
223
Anum_pg_conversion_connamespace,
227
{ConversionRelationName, /* CONOID */
232
ObjectIdAttributeNumber,
237
{GroupRelationName, /* GRONAME */
242
Anum_pg_group_groname,
247
{GroupRelationName, /* GROSYSID */
252
Anum_pg_group_grosysid,
257
{IndexRelationName, /* INDEXRELID */
259
Anum_pg_index_indrelid,
262
Anum_pg_index_indexrelid,
267
{InheritsRelationName, /* INHRELID */
268
InheritsRelidSeqnoIndex,
269
Anum_pg_inherits_inhrelid,
272
Anum_pg_inherits_inhrelid,
273
Anum_pg_inherits_inhseqno,
277
{LanguageRelationName, /* LANGNAME */
282
Anum_pg_language_lanname,
287
{LanguageRelationName, /* LANGOID */
292
ObjectIdAttributeNumber,
297
{NamespaceRelationName, /* NAMESPACENAME */
302
Anum_pg_namespace_nspname,
307
{NamespaceRelationName, /* NAMESPACEOID */
312
ObjectIdAttributeNumber,
317
{OperatorRelationName, /* OPERNAMENSP */
318
OperatorNameNspIndex,
322
Anum_pg_operator_oprname,
323
Anum_pg_operator_oprleft,
324
Anum_pg_operator_oprright,
325
Anum_pg_operator_oprnamespace
327
{OperatorRelationName, /* OPEROID */
332
ObjectIdAttributeNumber,
337
{ProcedureRelationName, /* PROCNAMENSP */
338
ProcedureNameNspIndex,
342
Anum_pg_proc_proname,
343
Anum_pg_proc_pronargs,
344
Anum_pg_proc_proargtypes,
345
Anum_pg_proc_pronamespace
347
{ProcedureRelationName, /* PROCOID */
352
ObjectIdAttributeNumber,
357
{RelationRelationName, /* RELNAMENSP */
359
ObjectIdAttributeNumber,
362
Anum_pg_class_relname,
363
Anum_pg_class_relnamespace,
367
{RelationRelationName, /* RELOID */
369
ObjectIdAttributeNumber,
372
ObjectIdAttributeNumber,
377
{RewriteRelationName, /* RULERELNAME */
378
RewriteRelRulenameIndex,
379
Anum_pg_rewrite_ev_class,
382
Anum_pg_rewrite_ev_class,
383
Anum_pg_rewrite_rulename,
387
{ShadowRelationName, /* SHADOWNAME */
392
Anum_pg_shadow_usename,
397
{ShadowRelationName, /* SHADOWSYSID */
402
Anum_pg_shadow_usesysid,
407
{StatisticRelationName, /* STATRELATT */
408
StatisticRelidAttnumIndex,
409
Anum_pg_statistic_starelid,
412
Anum_pg_statistic_starelid,
413
Anum_pg_statistic_staattnum,
417
{TypeRelationName, /* TYPENAMENSP */
419
Anum_pg_type_typrelid,
422
Anum_pg_type_typname,
423
Anum_pg_type_typnamespace,
427
{TypeRelationName, /* TYPEOID */
429
Anum_pg_type_typrelid,
432
ObjectIdAttributeNumber,
439
static CatCache *SysCache[
440
lengthof(cacheinfo)];
441
static int SysCacheSize = lengthof(cacheinfo);
442
static bool CacheInitialized = false;
446
* InitCatalogCache - initialize the caches
448
* Note that no database access is done here; we only allocate memory
449
* and initialize the cache structure. Interrogation of the database
450
* to complete initialization of a cache happens upon first use
454
InitCatalogCache(void)
458
Assert(!CacheInitialized);
460
MemSet((char *) SysCache, 0, sizeof(SysCache));
462
for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
464
SysCache[cacheId] = InitCatCache(cacheId,
465
cacheinfo[cacheId].name,
466
cacheinfo[cacheId].indname,
467
cacheinfo[cacheId].reloidattr,
468
cacheinfo[cacheId].nkeys,
469
cacheinfo[cacheId].key);
470
if (!PointerIsValid(SysCache[cacheId]))
471
elog(ERROR, "could not initialize cache %s (%d)",
472
cacheinfo[cacheId].name, cacheId);
474
CacheInitialized = true;
479
* InitCatalogCachePhase2 - finish initializing the caches
481
* Finish initializing all the caches, including necessary database
484
* This is *not* essential; normally we allow syscaches to be initialized
485
* on first use. However, it is useful as a mechanism to preload the
486
* relcache with entries for the most-commonly-used system catalogs.
487
* Therefore, we invoke this routine when we need to write a new relcache
491
InitCatalogCachePhase2(void)
495
Assert(CacheInitialized);
497
for (cacheId = 0; cacheId < SysCacheSize; cacheId++)
498
InitCatCachePhase2(SysCache[cacheId]);
505
* A layer on top of SearchCatCache that does the initialization and
506
* key-setting for you.
508
* Returns the cache copy of the tuple if one is found, NULL if not.
509
* The tuple is the 'cache' copy and must NOT be modified!
511
* When the caller is done using the tuple, call ReleaseSysCache()
512
* to release the reference count grabbed by SearchSysCache(). If this
513
* is not done, the tuple will remain locked in cache until end of
514
* transaction, which is tolerable but not desirable.
516
* CAUTION: The tuple that is returned must NOT be freed by the caller!
519
SearchSysCache(int cacheId,
525
if (cacheId < 0 || cacheId >= SysCacheSize ||
526
!PointerIsValid(SysCache[cacheId]))
527
elog(ERROR, "invalid cache id: %d", cacheId);
529
return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4);
534
* Release previously grabbed reference count on a tuple
537
ReleaseSysCache(HeapTuple tuple)
539
ReleaseCatCache(tuple);
545
* A convenience routine that does SearchSysCache and (if successful)
546
* returns a modifiable copy of the syscache entry. The original
547
* syscache entry is released before returning. The caller should
548
* heap_freetuple() the result when done with it.
551
SearchSysCacheCopy(int cacheId,
560
tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
561
if (!HeapTupleIsValid(tuple))
563
newtuple = heap_copytuple(tuple);
564
ReleaseSysCache(tuple);
569
* SearchSysCacheExists
571
* A convenience routine that just probes to see if a tuple can be found.
572
* No lock is retained on the syscache entry.
575
SearchSysCacheExists(int cacheId,
583
tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
584
if (!HeapTupleIsValid(tuple))
586
ReleaseSysCache(tuple);
593
* A convenience routine that does SearchSysCache and returns the OID
594
* of the found tuple, or InvalidOid if no tuple could be found.
595
* No lock is retained on the syscache entry.
598
GetSysCacheOid(int cacheId,
607
tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
608
if (!HeapTupleIsValid(tuple))
610
result = HeapTupleGetOid(tuple);
611
ReleaseSysCache(tuple);
617
* SearchSysCacheAttName
619
* This routine is equivalent to SearchSysCache on the ATTNAME cache,
620
* except that it will return NULL if the found attribute is marked
621
* attisdropped. This is convenient for callers that want to act as
622
* though dropped attributes don't exist.
625
SearchSysCacheAttName(Oid relid, const char *attname)
629
tuple = SearchSysCache(ATTNAME,
630
ObjectIdGetDatum(relid),
631
CStringGetDatum(attname),
633
if (!HeapTupleIsValid(tuple))
635
if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
637
ReleaseSysCache(tuple);
644
* SearchSysCacheCopyAttName
646
* As above, an attisdropped-aware version of SearchSysCacheCopy.
649
SearchSysCacheCopyAttName(Oid relid, const char *attname)
654
tuple = SearchSysCacheAttName(relid, attname);
655
if (!HeapTupleIsValid(tuple))
657
newtuple = heap_copytuple(tuple);
658
ReleaseSysCache(tuple);
663
* SearchSysCacheExistsAttName
665
* As above, an attisdropped-aware version of SearchSysCacheExists.
668
SearchSysCacheExistsAttName(Oid relid, const char *attname)
672
tuple = SearchSysCacheAttName(relid, attname);
673
if (!HeapTupleIsValid(tuple))
675
ReleaseSysCache(tuple);
683
* Given a tuple previously fetched by SearchSysCache(),
684
* extract a specific attribute.
686
* This is equivalent to using heap_getattr() on a tuple fetched
687
* from a non-cached relation. Usually, this is only used for attributes
688
* that could be NULL or variable length; the fixed-size attributes in
689
* a system table are accessed just by mapping the tuple onto the C struct
690
* declarations from include/catalog/.
692
* As with heap_getattr(), if the attribute is of a pass-by-reference type
693
* then a pointer into the tuple data area is returned --- the caller must
694
* not modify or pfree the datum!
697
SysCacheGetAttr(int cacheId, HeapTuple tup,
698
AttrNumber attributeNumber,
702
* We just need to get the TupleDesc out of the cache entry, and then
703
* we can apply heap_getattr(). We expect that the cache control data
704
* is currently valid --- if the caller recently fetched the tuple,
707
if (cacheId < 0 || cacheId >= SysCacheSize)
708
elog(ERROR, "invalid cache id: %d", cacheId);
709
if (!PointerIsValid(SysCache[cacheId]) ||
710
!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
711
elog(ERROR, "missing cache data for cache id %d", cacheId);
713
return heap_getattr(tup, attributeNumber,
714
SysCache[cacheId]->cc_tupdesc,
719
* List-search interface
722
SearchSysCacheList(int cacheId, int nkeys,
723
Datum key1, Datum key2, Datum key3, Datum key4)
725
if (cacheId < 0 || cacheId >= SysCacheSize ||
726
!PointerIsValid(SysCache[cacheId]))
727
elog(ERROR, "invalid cache id: %d", cacheId);
729
return SearchCatCacheList(SysCache[cacheId], nkeys,
730
key1, key2, key3, key4);