1 /*-------------------------------------------------------------------------
4 * System cache management routines
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.30 1999/07/16 05:23:21 momjian Exp $
13 * These routines allow the parser/planner/executor to perform
14 * rapid lookups on the contents of the system catalogs.
16 * see catalog/syscache.h for a list of the cache id's
18 *-------------------------------------------------------------------------
23 #include "access/heapam.h"
24 #include "catalog/catname.h"
25 #include "catalog/pg_aggregate.h"
26 #include "catalog/pg_amop.h"
27 #include "catalog/pg_group.h"
28 #include "catalog/pg_index.h"
29 #include "catalog/pg_inherits.h"
30 #include "catalog/pg_language.h"
31 #include "catalog/pg_listener.h"
32 #include "catalog/pg_opclass.h"
33 #include "catalog/pg_operator.h"
34 #include "catalog/pg_proc.h"
35 #include "catalog/pg_rewrite.h"
36 #include "catalog/pg_shadow.h"
37 #include "catalog/pg_type.h"
38 #include "utils/catcache.h"
40 extern bool AMI_OVERRIDE; /* XXX style */
42 #include "utils/syscache.h"
43 #include "catalog/indexing.h"
45 typedef HeapTuple (*ScanFunc) ();
48 * Warning: cacheinfo[] below is changed, then be sure and
49 * update the magic constants in syscache.h!
52 static struct cachedesc cacheinfo[] = {
53 {AccessMethodOperatorRelationName, /* AMOPOPID */
56 Anum_pg_amop_amopclaid,
61 sizeof(FormData_pg_amop),
64 {AccessMethodOperatorRelationName, /* AMOPSTRATEGY */
68 Anum_pg_amop_amopclaid,
69 Anum_pg_amop_amopstrategy,
72 sizeof(FormData_pg_amop),
75 {AttributeRelationName, /* ATTNAME */
78 Anum_pg_attribute_attrelid,
79 Anum_pg_attribute_attname,
85 (ScanFunc) AttributeNameIndexScan},
86 {AttributeRelationName, /* ATTNUM */
89 Anum_pg_attribute_attrelid,
90 Anum_pg_attribute_attnum,
96 (ScanFunc) AttributeNumIndexScan},
97 {IndexRelationName, /* INDEXRELID */
100 Anum_pg_index_indexrelid,
105 offsetof(FormData_pg_index, indpred),
108 {LanguageRelationName, /* LANNAME */
111 Anum_pg_language_lanname,
116 offsetof(FormData_pg_language, lancompiler),
119 {OperatorRelationName, /* OPRNAME */
122 Anum_pg_operator_oprname,
123 Anum_pg_operator_oprleft,
124 Anum_pg_operator_oprright,
125 Anum_pg_operator_oprkind
127 sizeof(FormData_pg_operator),
130 {OperatorRelationName, /* OPROID */
133 ObjectIdAttributeNumber,
138 sizeof(FormData_pg_operator),
141 {ProcedureRelationName, /* PRONAME */
144 Anum_pg_proc_proname,
145 Anum_pg_proc_pronargs,
146 Anum_pg_proc_proargtypes,
149 offsetof(FormData_pg_proc, prosrc),
151 (ScanFunc) ProcedureNameIndexScan},
152 {ProcedureRelationName, /* PROOID */
155 ObjectIdAttributeNumber,
160 offsetof(FormData_pg_proc, prosrc),
162 (ScanFunc) ProcedureOidIndexScan},
163 {RelationRelationName, /* RELNAME */
166 Anum_pg_class_relname,
173 (ScanFunc) ClassNameIndexScan},
174 {RelationRelationName, /* RELOID */
177 ObjectIdAttributeNumber,
184 (ScanFunc) ClassOidIndexScan},
185 {TypeRelationName, /* TYPNAME */
188 Anum_pg_type_typname,
193 offsetof(FormData_pg_type, typalign) +sizeof(char),
196 {TypeRelationName, /* TYPOID */
199 ObjectIdAttributeNumber,
204 offsetof(FormData_pg_type, typalign) +sizeof(char),
207 {AccessMethodRelationName, /* AMNAME */
215 sizeof(FormData_pg_am),
218 {OperatorClassRelationName, /* CLANAME */
221 Anum_pg_opclass_opcname,
226 sizeof(FormData_pg_opclass),
229 {IndexRelationName, /* INDRELIDKEY *//* never used */
232 Anum_pg_index_indrelid,
233 Anum_pg_index_indkey,
237 offsetof(FormData_pg_index, indpred),
240 {InheritsRelationName, /* INHRELID */
243 Anum_pg_inherits_inhrel,
244 Anum_pg_inherits_inhseqno,
248 sizeof(FormData_pg_inherits),
251 {RewriteRelationName, /* RULOID */
254 ObjectIdAttributeNumber,
259 offsetof(FormData_pg_rewrite, ev_qual),
262 {AggregateRelationName, /* AGGNAME */
265 Anum_pg_aggregate_aggname,
266 Anum_pg_aggregate_aggbasetype,
270 offsetof(FormData_pg_aggregate, agginitval1),
273 {ListenerRelationName, /* LISTENREL */
276 Anum_pg_listener_relname,
277 Anum_pg_listener_pid,
281 sizeof(FormData_pg_listener),
284 {ShadowRelationName, /* USENAME */
287 Anum_pg_shadow_usename,
292 sizeof(FormData_pg_shadow),
295 {ShadowRelationName, /* USESYSID */
298 Anum_pg_shadow_usesysid,
303 sizeof(FormData_pg_shadow),
306 {GroupRelationName, /* GRONAME */
309 Anum_pg_group_groname,
314 offsetof(FormData_pg_group, grolist[0]),
317 {GroupRelationName, /* GROSYSID */
320 Anum_pg_group_grosysid,
325 offsetof(FormData_pg_group, grolist[0]),
328 {RewriteRelationName, /* REWRITENAME */
331 Anum_pg_rewrite_rulename,
336 offsetof(FormData_pg_rewrite, ev_qual),
339 {ProcedureRelationName, /* PROSRC */
347 offsetof(FormData_pg_proc, prosrc),
349 (ScanFunc) ProcedureSrcIndexScan},
350 {OperatorClassRelationName, /* CLADEFTYPE */
353 Anum_pg_opclass_opcdeftype,
358 sizeof(FormData_pg_opclass),
361 {LanguageRelationName, /* LANOID */
364 ObjectIdAttributeNumber,
369 offsetof(FormData_pg_language, lancompiler),
374 static struct catcache *SysCache[lengthof(cacheinfo)];
375 static int32 SysCacheSize = lengthof(cacheinfo);
381 * Make sure the SysCache structure is zero'd.
386 MemSet((char *) SysCache, 0, SysCacheSize * sizeof(struct catcache *));
391 * This function was written because the initialized catalog caches
392 * are used to determine which caches may contain tuples which need
393 * to be invalidated in other backends.
398 int cacheId; /* XXX type */
402 for (cacheId = 0; cacheId < SysCacheSize; cacheId += 1)
405 Assert(!PointerIsValid((Pointer) SysCache[cacheId]));
407 SysCache[cacheId] = InitSysCache(cacheinfo[cacheId].name,
408 cacheinfo[cacheId].indname,
410 cacheinfo[cacheId].nkeys,
411 cacheinfo[cacheId].key,
412 cacheinfo[cacheId].iScanFunc);
413 if (!PointerIsValid((char *) SysCache[cacheId]))
416 "InitCatalogCache: Can't init cache %s(%d)",
417 cacheinfo[cacheId].name,
426 * SearchSysCacheTupleCopy
428 * This is like SearchSysCacheTuple, except it returns a copy of the tuple
429 * that the user is required to pfree().
432 SearchSysCacheTupleCopy(int cacheId, /* cache selection code */
440 cachetup = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
441 if (PointerIsValid(cachetup))
442 return heap_copytuple(cachetup);
444 return cachetup; /* NULL */
449 * SearchSysCacheTuple
451 * A layer on top of SearchSysCache that does the initialization and
452 * key-setting for you.
454 * Returns the cache copy of the tuple if one is found, NULL if not.
455 * The tuple is the 'cache' copy.
457 * XXX The tuple that is returned is NOT supposed to be pfree'd!
460 SearchSysCacheTuple(int cacheId,/* cache selection code */
468 if (cacheId < 0 || cacheId >= SysCacheSize)
470 elog(ERROR, "SearchSysCacheTuple: Bad cache id %d", cacheId);
471 return (HeapTuple) NULL;
474 Assert(AMI_OVERRIDE || PointerIsValid(SysCache[cacheId]));
476 if (!PointerIsValid(SysCache[cacheId]))
478 SysCache[cacheId] = InitSysCache(cacheinfo[cacheId].name,
479 cacheinfo[cacheId].indname,
481 cacheinfo[cacheId].nkeys,
482 cacheinfo[cacheId].key,
483 cacheinfo[cacheId].iScanFunc);
484 if (!PointerIsValid(SysCache[cacheId]))
486 "InitCatalogCache: Can't init cache %s(%d)",
487 cacheinfo[cacheId].name,
491 tp = SearchSysCache(SysCache[cacheId], key1, key2, key3, key4);
492 if (!HeapTupleIsValid(tp))
496 "SearchSysCacheTuple: Search %s(%d) %d %d %d %d failed",
497 cacheinfo[cacheId].name,
498 cacheId, key1, key2, key3, key4);
500 return (HeapTuple) NULL;
506 * SearchSysCacheStruct
507 * Fills 's' with the information retrieved by calling SearchSysCache()
508 * with arguments key1...key4. Retrieves only the portion of the tuple
509 * which is not variable-length.
511 * NOTE: we are assuming that non-variable-length fields in the system
512 * catalogs will always be defined!
514 * Returns 1L if a tuple was found, 0L if not.
517 SearchSysCacheStruct(int cacheId, /* cache selection code */
518 char *returnStruct, /* (preallocated!) */
526 if (!PointerIsValid(returnStruct))
528 elog(ERROR, "SearchSysCacheStruct: No receiving struct");
531 tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
532 if (!HeapTupleIsValid(tp))
534 memcpy(returnStruct, (char *) GETSTRUCT(tp), cacheinfo[cacheId].size);
540 * SearchSysCacheGetAttribute
541 * Returns the attribute corresponding to 'attributeNumber' for
542 * a given cached tuple. This routine usually needs to be used for
543 * attributes that might be NULL or might be at a variable offset
546 * XXX This re-opens the relation, so this is slower than just pulling
547 * fixed-location fields out of the struct returned by SearchSysCacheTuple.
549 * [callers all assume this returns a (struct varlena *). -ay 10/94]
552 SearchSysCacheGetAttribute(int cacheId,
553 AttrNumber attributeNumber,
562 int32 attributeLength,
565 Datum attributeValue;
568 tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
569 cacheName = cacheinfo[cacheId].name;
571 if (!HeapTupleIsValid(tp))
575 "SearchSysCacheGetAttribute: Lookup in %s(%d) failed",
577 #endif /* defined(CACHEDEBUG) */
581 relation = heap_openr(cacheName);
583 if (attributeNumber < 0 &&
584 attributeNumber > FirstLowInvalidHeapAttributeNumber)
586 attributeLength = heap_sysattrlen(attributeNumber);
587 attributeByValue = heap_sysattrbyval(attributeNumber);
589 else if (attributeNumber > 0 &&
590 attributeNumber <= relation->rd_rel->relnatts)
592 attributeLength = relation->rd_att->attrs[attributeNumber - 1]->attlen;
593 attributeByValue = relation->rd_att->attrs[attributeNumber - 1]->attbyval;
598 "SearchSysCacheGetAttribute: Bad attr # %d in %s(%d)",
599 attributeNumber, cacheName, cacheId);
603 attributeValue = heap_getattr(tp,
605 RelationGetDescr(relation),
612 * Used to be an elog(DEBUG, ...) here and a claim that it should
613 * be a FATAL error, I don't think either is warranted -mer 6/9/92
618 if (attributeByValue)
619 returnValue = (void *) attributeValue;
623 int size = (attributeLength < 0)
624 ? VARSIZE((struct varlena *) attributeValue) /* variable length */
625 : attributeLength; /* fixed length */
627 tmp = (char *) palloc(size);
628 memcpy(tmp, (void *) attributeValue, size);
629 returnValue = (void *) tmp;
632 heap_close(relation);
637 * TypeDefaultRetrieve
639 * Given a type OID, return the typdefault field associated with that
640 * type. The result is a Datum, and points to palloc'd storage for
641 * non-pass-by-value types.
643 * [identical to get_typdefault, expecting a (struct varlena *) as ret val.
644 * some day, either of the functions should be removed -ay 10/94]
647 TypeDefaultRetrieve(Oid typId)
649 struct varlena *typDefault;
658 * First, see if there is a non-null typdefault field (usually there isn't)
660 typDefault = (struct varlena *)
661 SearchSysCacheGetAttribute(TYPOID,
662 Anum_pg_type_typdefault,
663 ObjectIdGetDatum(typId),
666 if (typDefault == NULL)
669 elog(DEBUG, "TypeDefaultRetrieve: No extractable typdefault in %s(%d)",
670 cacheinfo[TYPOID].name, TYPOID);
671 #endif /* defined(CACHEDEBUG) */
675 dataSize = VARSIZE(typDefault) - VARHDRSZ;
678 * Need the type's length and byVal fields.
680 * XXX silly to repeat the syscache search that SearchSysCacheGetAttribute
681 * just did --- but at present this path isn't taken often enough to
682 * make it worth fixing.
684 typeTuple = SearchSysCacheTuple(TYPOID,
685 ObjectIdGetDatum(typId),
688 if (!HeapTupleIsValid(typeTuple))
690 /* should never get here, really... */
692 elog(DEBUG, "TypeDefaultRetrieve: Lookup in %s(%d) failed",
693 cacheinfo[TYPOID].name, TYPOID);
694 #endif /* defined(CACHEDEBUG) */
698 type = (Form_pg_type) GETSTRUCT(typeTuple);
699 typLen = type->typlen;
700 typByVal = type->typbyval;
708 if (dataSize == typLen)
713 memcpy((char *) &i8, VARDATA(typDefault), sizeof(int8));
717 memcpy((char *) &i16, VARDATA(typDefault), sizeof(int16));
721 memcpy((char *) &i32, VARDATA(typDefault), sizeof(int32));
724 returnValue = (void *) i32;
731 if ((typLen < 0 && dataSize < 0) || dataSize != typLen)
735 returnValue = (void *) palloc(VARSIZE(typDefault));
736 memcpy((char *) returnValue,
738 (int) VARSIZE(typDefault));