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.26 1999/05/25 22:42:15 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 *-------------------------------------------------------------------------
22 #include "access/heapam.h"
23 #include "access/htup.h"
24 #include "catalog/catname.h"
25 #include "utils/catcache.h"
27 #include <regex/utils.h>
34 * hardwired attribute information comes from system catalog files.
37 #include "catalog/pg_am.h"
38 #include "catalog/pg_amop.h"
39 #include "catalog/pg_attribute.h"
40 #include "catalog/pg_group.h"
41 #include "catalog/pg_index.h"
42 #include "catalog/pg_inherits.h"
43 #include "catalog/pg_language.h"
44 #include "catalog/pg_opclass.h"
45 #include "catalog/pg_operator.h"
46 #include "catalog/pg_proc.h"
47 #include "catalog/pg_class.h"
48 #include "catalog/pg_type.h"
49 #include "catalog/pg_rewrite.h"
50 #include "catalog/pg_aggregate.h"
51 #include "catalog/pg_shadow.h"
52 #include "storage/large_object.h"
53 #include "catalog/pg_listener.h"
55 extern bool AMI_OVERRIDE; /* XXX style */
57 #include "utils/syscache.h"
58 #include "catalog/indexing.h"
60 typedef HeapTuple (*ScanFunc) ();
63 * Warning: cacheinfo[] below is changed, then be sure and
64 * update the magic constants in syscache.h!
67 static struct cachedesc cacheinfo[] = {
68 {AccessMethodOperatorRelationName, /* AMOPOPID */
71 Anum_pg_amop_amopclaid,
76 sizeof(FormData_pg_amop),
79 {AccessMethodOperatorRelationName, /* AMOPSTRATEGY */
83 Anum_pg_amop_amopclaid,
84 Anum_pg_amop_amopstrategy,
87 sizeof(FormData_pg_amop),
90 {AttributeRelationName, /* ATTNAME */
93 Anum_pg_attribute_attrelid,
94 Anum_pg_attribute_attname,
100 (ScanFunc) AttributeNameIndexScan},
101 {AttributeRelationName, /* ATTNUM */
104 Anum_pg_attribute_attrelid,
105 Anum_pg_attribute_attnum,
109 ATTRIBUTE_TUPLE_SIZE,
111 (ScanFunc) AttributeNumIndexScan},
112 {IndexRelationName, /* INDEXRELID */
115 Anum_pg_index_indexrelid,
120 offsetof(FormData_pg_index, indpred),
123 {LanguageRelationName, /* LANNAME */
126 Anum_pg_language_lanname,
131 offsetof(FormData_pg_language, lancompiler),
134 {OperatorRelationName, /* OPRNAME */
137 Anum_pg_operator_oprname,
138 Anum_pg_operator_oprleft,
139 Anum_pg_operator_oprright,
140 Anum_pg_operator_oprkind
142 sizeof(FormData_pg_operator),
145 {OperatorRelationName, /* OPROID */
148 ObjectIdAttributeNumber,
153 sizeof(FormData_pg_operator),
156 {ProcedureRelationName, /* PRONAME */
159 Anum_pg_proc_proname,
160 Anum_pg_proc_pronargs,
161 Anum_pg_proc_proargtypes,
164 offsetof(FormData_pg_proc, prosrc),
166 (ScanFunc) ProcedureNameIndexScan},
167 {ProcedureRelationName, /* PROOID */
170 ObjectIdAttributeNumber,
175 offsetof(FormData_pg_proc, prosrc),
177 (ScanFunc) ProcedureOidIndexScan},
178 {RelationRelationName, /* RELNAME */
181 Anum_pg_class_relname,
188 (ScanFunc) ClassNameIndexScan},
189 {RelationRelationName, /* RELOID */
192 ObjectIdAttributeNumber,
199 (ScanFunc) ClassOidIndexScan},
200 {TypeRelationName, /* TYPNAME */
203 Anum_pg_type_typname,
208 offsetof(FormData_pg_type, typalign) +sizeof(char),
211 {TypeRelationName, /* TYPOID */
214 ObjectIdAttributeNumber,
219 offsetof(FormData_pg_type, typalign) +sizeof(char),
222 {AccessMethodRelationName, /* AMNAME */
230 sizeof(FormData_pg_am),
233 {OperatorClassRelationName, /* CLANAME */
236 Anum_pg_opclass_opcname,
241 sizeof(FormData_pg_opclass),
244 {IndexRelationName, /* INDRELIDKEY *//* never used */
247 Anum_pg_index_indrelid,
248 Anum_pg_index_indkey,
252 offsetof(FormData_pg_index, indpred),
255 {InheritsRelationName, /* INHRELID */
258 Anum_pg_inherits_inhrel,
259 Anum_pg_inherits_inhseqno,
263 sizeof(FormData_pg_inherits),
266 {RewriteRelationName, /* RULOID */
269 ObjectIdAttributeNumber,
274 offsetof(FormData_pg_rewrite, ev_qual),
277 {AggregateRelationName, /* AGGNAME */
280 Anum_pg_aggregate_aggname,
281 Anum_pg_aggregate_aggbasetype,
285 offsetof(FormData_pg_aggregate, agginitval1),
288 {ListenerRelationName, /* LISTENREL */
291 Anum_pg_listener_relname,
292 Anum_pg_listener_pid,
296 sizeof(FormData_pg_listener),
299 {ShadowRelationName, /* USENAME */
302 Anum_pg_shadow_usename,
307 sizeof(FormData_pg_shadow),
310 {ShadowRelationName, /* USESYSID */
313 Anum_pg_shadow_usesysid,
318 sizeof(FormData_pg_shadow),
321 {GroupRelationName, /* GRONAME */
324 Anum_pg_group_groname,
329 offsetof(FormData_pg_group, grolist[0]),
332 {GroupRelationName, /* GROSYSID */
335 Anum_pg_group_grosysid,
340 offsetof(FormData_pg_group, grolist[0]),
343 {RewriteRelationName, /* REWRITENAME */
346 Anum_pg_rewrite_rulename,
351 offsetof(FormData_pg_rewrite, ev_qual),
354 {ProcedureRelationName, /* PROSRC */
362 offsetof(FormData_pg_proc, prosrc),
364 (ScanFunc) ProcedureSrcIndexScan},
365 {OperatorClassRelationName, /* CLADEFTYPE */
368 Anum_pg_opclass_opcdeftype,
373 sizeof(FormData_pg_opclass),
376 {LanguageRelationName, /* LANOID */
379 ObjectIdAttributeNumber,
384 offsetof(FormData_pg_language, lancompiler),
389 static struct catcache *SysCache[
390 lengthof(cacheinfo)];
391 static int32 SysCacheSize = lengthof(cacheinfo);
397 * Make sure the SysCache structure is zero'd.
402 MemSet((char *) SysCache, 0, SysCacheSize * sizeof(struct catcache *));
407 * This function was written because the initialized catalog caches
408 * are used to determine which caches may contain tuples which need
409 * to be invalidated in other backends.
414 int cacheId; /* XXX type */
418 for (cacheId = 0; cacheId < SysCacheSize; cacheId += 1)
421 Assert(!PointerIsValid((Pointer) SysCache[cacheId]));
423 SysCache[cacheId] = InitSysCache(cacheinfo[cacheId].name,
424 cacheinfo[cacheId].indname,
426 cacheinfo[cacheId].nkeys,
427 cacheinfo[cacheId].key,
428 cacheinfo[cacheId].iScanFunc);
429 if (!PointerIsValid((char *) SysCache[cacheId]))
432 "InitCatalogCache: Can't init cache %s(%d)",
433 cacheinfo[cacheId].name,
442 * SearchSysCacheTupleCopy
444 * THis is like SearchSysCacheTuple, except it returns a copy of the tuple
445 * that the user is required to pfree().
448 SearchSysCacheTupleCopy(int cacheId, /* cache selection code */
456 cachetup = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
457 if (PointerIsValid(cachetup))
458 return heap_copytuple(cachetup);
460 return cachetup; /* NULL */
465 * SearchSysCacheTuple
467 * A layer on top of SearchSysCache that does the initialization and
468 * key-setting for you.
470 * Returns the cache copy of the tuple if one is found, NULL if not.
471 * The tuple is the 'cache' copy.
473 * XXX The tuple that is returned is NOT supposed to be pfree'd!
476 SearchSysCacheTuple(int cacheId,/* cache selection code */
484 if (cacheId < 0 || cacheId >= SysCacheSize)
486 elog(ERROR, "SearchSysCacheTuple: Bad cache id %d", cacheId);
487 return (HeapTuple) NULL;
490 Assert(AMI_OVERRIDE || PointerIsValid(SysCache[cacheId]));
492 if (!PointerIsValid(SysCache[cacheId]))
494 SysCache[cacheId] = InitSysCache(cacheinfo[cacheId].name,
495 cacheinfo[cacheId].indname,
497 cacheinfo[cacheId].nkeys,
498 cacheinfo[cacheId].key,
499 cacheinfo[cacheId].iScanFunc);
500 if (!PointerIsValid(SysCache[cacheId]))
502 "InitCatalogCache: Can't init cache %s(%d)",
503 cacheinfo[cacheId].name,
507 tp = SearchSysCache(SysCache[cacheId], key1, key2, key3, key4);
508 if (!HeapTupleIsValid(tp))
512 "SearchSysCacheTuple: Search %s(%d) %d %d %d %d failed",
513 cacheinfo[cacheId].name,
514 cacheId, key1, key2, key3, key4);
516 return (HeapTuple) NULL;
522 * SearchSysCacheStruct
523 * Fills 's' with the information retrieved by calling SearchSysCache()
524 * with arguments key1...key4. Retrieves only the portion of the tuple
525 * which is not variable-length.
527 * NOTE: we are assuming that non-variable-length fields in the system
528 * catalogs will always be defined!
530 * Returns 1L if a tuple was found, 0L if not.
533 SearchSysCacheStruct(int cacheId, /* cache selection code */
534 char *returnStruct, /* (preallocated!) */
542 if (!PointerIsValid(returnStruct))
544 elog(ERROR, "SearchSysCacheStruct: No receiving struct");
547 tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
548 if (!HeapTupleIsValid(tp))
550 memmove(returnStruct, (char *) GETSTRUCT(tp), cacheinfo[cacheId].size);
556 * SearchSysCacheGetAttribute
557 * Returns the attribute corresponding to 'attributeNumber' for
558 * a given cached tuple.
560 * XXX This re-opens a relation, so this is slower.
562 * [callers all assume this returns a (struct varlena *). -ay 10/94]
565 SearchSysCacheGetAttribute(int cacheId,
566 AttrNumber attributeNumber,
575 int32 attributeLength,
578 Datum attributeValue;
581 tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
582 cacheName = cacheinfo[cacheId].name;
584 if (!HeapTupleIsValid(tp))
588 "SearchSysCacheGetAttribute: Lookup in %s(%d) failed",
590 #endif /* defined(CACHEDEBUG) */
594 relation = heap_openr(cacheName);
596 if (attributeNumber < 0 &&
597 attributeNumber > FirstLowInvalidHeapAttributeNumber)
599 attributeLength = heap_sysattrlen(attributeNumber);
600 attributeByValue = heap_sysattrbyval(attributeNumber);
602 else if (attributeNumber > 0 &&
603 attributeNumber <= relation->rd_rel->relnatts)
605 attributeLength = relation->rd_att->attrs[attributeNumber - 1]->attlen;
606 attributeByValue = relation->rd_att->attrs[attributeNumber - 1]->attbyval;
611 "SearchSysCacheGetAttribute: Bad attr # %d in %s(%d)",
612 attributeNumber, cacheName, cacheId);
616 attributeValue = heap_getattr(tp,
618 RelationGetDescr(relation),
625 * Used to be an elog(DEBUG, ...) here and a claim that it should
626 * be a FATAL error, I don't think either is warranted -mer 6/9/92
631 if (attributeByValue)
632 returnValue = (void *) attributeValue;
636 int size = (attributeLength < 0)
637 ? VARSIZE((struct varlena *) attributeValue) /* variable length */
638 : attributeLength; /* fixed length */
640 tmp = (char *) palloc(size);
641 memmove(tmp, (void *) attributeValue, size);
642 returnValue = (void *) tmp;
645 heap_close(relation);
650 * TypeDefaultRetrieve
652 * Given a type OID, return the typdefault field associated with that
653 * type. The typdefault is returned as the car of a dotted pair which
654 * is passed to TypeDefaultRetrieve by the calling routine.
656 * Returns a fixnum for types which are passed by value and a ppreserve'd
657 * vectori for types which are not.
659 * [identical to get_typdefault, expecting a (struct varlena *) as ret val.
660 * some day, either of the functions should be removed -ay 10/94]
663 TypeDefaultRetrieve(Oid typId)
669 struct varlena *typDefault;
673 typeTuple = SearchSysCacheTuple(TYPOID,
674 ObjectIdGetDatum(typId),
677 if (!HeapTupleIsValid(typeTuple))
680 elog(DEBUG, "TypeDefaultRetrieve: Lookup in %s(%d) failed",
681 cacheinfo[TYPOID].name, TYPOID);
682 #endif /* defined(CACHEDEBUG) */
686 type = (Form_pg_type) GETSTRUCT(typeTuple);
687 typByVal = type->typbyval;
688 typLen = type->typlen;
690 typDefault = (struct varlena *)
691 SearchSysCacheGetAttribute(TYPOID,
692 Anum_pg_type_typdefault,
693 ObjectIdGetDatum(typId),
696 if (typDefault == (struct varlena *) NULL)
699 elog(DEBUG, "TypeDefaultRetrieve: No extractable typdefault in %s(%d)",
700 cacheinfo[TYPOID].name, TYPOID);
701 #endif /* defined(CACHEDEBUG) */
705 dataSize = VARSIZE(typDefault) - VARHDRSZ;
713 if (dataSize == typLen)
718 memmove((char *) &i8, VARDATA(typDefault), sizeof(int8));
722 memmove((char *) &i16, VARDATA(typDefault), sizeof(int16));
726 memmove((char *) &i32, VARDATA(typDefault), sizeof(int32));
729 returnValue = (void *) i32;
736 if ((typLen < 0 && dataSize < 0) || dataSize != typLen)
740 returnValue = (void *) palloc(VARSIZE(typDefault));
741 memmove((char *) returnValue,
743 (int) VARSIZE(typDefault));