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.13 1998/01/31 04:38:54 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_user.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 */
70 {Anum_pg_amop_amopclaid,
74 sizeof(FormData_pg_amop),
77 {AccessMethodOperatorRelationName, /* AMOPSTRATEGY */
80 Anum_pg_amop_amopclaid,
81 Anum_pg_amop_amopstrategy,
83 sizeof(FormData_pg_amop),
86 {AttributeRelationName, /* ATTNAME */
88 {Anum_pg_attribute_attrelid,
89 Anum_pg_attribute_attname,
94 (ScanFunc) AttributeNameIndexScan},
95 {AttributeRelationName, /* ATTNUM */
97 {Anum_pg_attribute_attrelid,
98 Anum_pg_attribute_attnum,
101 ATTRIBUTE_TUPLE_SIZE,
103 (ScanFunc) AttributeNumIndexScan},
104 {IndexRelationName, /* INDEXRELID */
106 {Anum_pg_index_indexrelid,
110 offsetof(FormData_pg_index, indpred),
113 {LanguageRelationName, /* LANNAME */
115 {Anum_pg_language_lanname,
119 offsetof(FormData_pg_language, lancompiler),
122 {OperatorRelationName, /* OPRNAME */
124 {Anum_pg_operator_oprname,
125 Anum_pg_operator_oprleft,
126 Anum_pg_operator_oprright,
127 Anum_pg_operator_oprkind},
128 sizeof(FormData_pg_operator),
131 {OperatorRelationName, /* OPROID */
133 {ObjectIdAttributeNumber,
137 sizeof(FormData_pg_operator),
140 {ProcedureRelationName, /* PRONAME */
142 {Anum_pg_proc_proname,
143 Anum_pg_proc_pronargs,
144 Anum_pg_proc_proargtypes,
146 offsetof(FormData_pg_proc, prosrc),
148 (ScanFunc) ProcedureNameIndexScan},
149 {ProcedureRelationName, /* PROOID */
151 {ObjectIdAttributeNumber,
155 offsetof(FormData_pg_proc, prosrc),
157 (ScanFunc) ProcedureOidIndexScan},
158 {RelationRelationName, /* RELNAME */
160 {Anum_pg_class_relname,
166 (ScanFunc) ClassNameIndexScan},
167 {RelationRelationName, /* RELOID */
169 {ObjectIdAttributeNumber,
175 (ScanFunc) ClassOidIndexScan},
176 {TypeRelationName, /* TYPNAME */
178 {Anum_pg_type_typname,
182 offsetof(TypeTupleFormData, typalign) + sizeof(char),
185 {TypeRelationName, /* TYPOID */
187 {ObjectIdAttributeNumber,
191 offsetof(TypeTupleFormData, typalign) +sizeof(char),
194 {AccessMethodRelationName, /* AMNAME */
200 sizeof(FormData_pg_am),
203 {OperatorClassRelationName, /* CLANAME */
205 {Anum_pg_opclass_opcname,
209 sizeof(FormData_pg_opclass),
212 {IndexRelationName, /* INDRELIDKEY */
214 {Anum_pg_index_indrelid,
215 Anum_pg_index_indkey,
218 offsetof(FormData_pg_index, indpred),
221 {InheritsRelationName, /* INHRELID */
223 {Anum_pg_inherits_inhrel,
224 Anum_pg_inherits_inhseqno,
227 sizeof(FormData_pg_inherits),
230 {RewriteRelationName, /* RULOID */
232 {ObjectIdAttributeNumber,
236 offsetof(FormData_pg_rewrite, ev_qual),
239 {AggregateRelationName, /* AGGNAME */
241 {Anum_pg_aggregate_aggname,
242 Anum_pg_aggregate_aggbasetype,
245 offsetof(FormData_pg_aggregate, agginitval1),
248 {ListenerRelationName, /* LISTENREL */
250 {Anum_pg_listener_relname,
251 Anum_pg_listener_pid,
254 sizeof(FormData_pg_listener),
257 {UserRelationName, /* USENAME */
259 {Anum_pg_user_usename,
263 sizeof(FormData_pg_user),
266 {UserRelationName, /* USESYSID */
268 {Anum_pg_user_usesysid,
272 sizeof(FormData_pg_user),
275 {GroupRelationName, /* GRONAME */
277 {Anum_pg_group_groname,
281 offsetof(FormData_pg_group, grolist[0]),
284 {GroupRelationName, /* GROSYSID */
286 {Anum_pg_group_grosysid,
290 offsetof(FormData_pg_group, grolist[0]),
293 {RewriteRelationName, /* REWRITENAME */
295 {Anum_pg_rewrite_rulename,
299 offsetof(FormData_pg_rewrite, ev_qual),
302 {ProcedureRelationName, /* PROSRC */
304 {Anum_pg_proc_prosrc,
308 offsetof(FormData_pg_proc, prosrc),
310 (ScanFunc) ProcedureSrcIndexScan},
311 {OperatorClassRelationName, /* CLADEFTYPE */
313 {Anum_pg_opclass_opcdeftype,
317 sizeof(FormData_pg_opclass),
320 {LanguageRelationName, /* LANOID */
322 {ObjectIdAttributeNumber,
326 offsetof(FormData_pg_language, lancompiler),
331 static struct catcache *SysCache[
332 lengthof(cacheinfo)];
333 static int32 SysCacheSize = lengthof(cacheinfo);
339 * Make sure the SysCache structure is zero'd.
344 MemSet((char *) SysCache, 0, SysCacheSize * sizeof(struct catcache *));
349 * This function was written because the initialized catalog caches
350 * are used to determine which caches may contain tuples which need
351 * to be invalidated in other backends.
356 int cacheId; /* XXX type */
360 for (cacheId = 0; cacheId < SysCacheSize; cacheId += 1)
363 Assert(!PointerIsValid((Pointer) SysCache[cacheId]));
366 InitSysCache(cacheinfo[cacheId].name,
367 cacheinfo[cacheId].indname,
369 cacheinfo[cacheId].nkeys,
370 cacheinfo[cacheId].key,
371 cacheinfo[cacheId].iScanFunc);
372 if (!PointerIsValid((char *) SysCache[cacheId]))
375 "InitCatalogCache: Can't init cache %.16s(%d)",
376 cacheinfo[cacheId].name,
385 * SearchSysCacheTuple--
387 * A layer on top of SearchSysCache that does the initialization and
388 * key-setting for you.
390 * Returns the tuple if one is found, NULL if not.
392 * XXX The tuple that is returned is NOT supposed to be pfree'd!
395 SearchSysCacheTuple(int cacheId, /* cache selection code */
401 register HeapTuple tp;
403 if (cacheId < 0 || cacheId >= SysCacheSize)
405 elog(ERROR, "SearchSysCacheTuple: Bad cache id %d", cacheId);
406 return ((HeapTuple) NULL);
411 Assert(PointerIsValid(SysCache[cacheId]));
415 if (!PointerIsValid(SysCache[cacheId]))
418 InitSysCache(cacheinfo[cacheId].name,
419 cacheinfo[cacheId].indname,
421 cacheinfo[cacheId].nkeys,
422 cacheinfo[cacheId].key,
423 cacheinfo[cacheId].iScanFunc);
424 if (!PointerIsValid(SysCache[cacheId]))
427 "InitCatalogCache: Can't init cache %.16s(%d)",
428 cacheinfo[cacheId].name,
435 tp = SearchSysCache(SysCache[cacheId], key1, key2, key3, key4);
436 if (!HeapTupleIsValid(tp))
440 "SearchSysCacheTuple: Search %s(%d) %d %d %d %d failed",
441 (*cacheinfo[cacheId].name)->data,
442 cacheId, key1, key2, key3, key4);
444 return ((HeapTuple) NULL);
450 * SearchSysCacheStruct--
451 * Fills 's' with the information retrieved by calling SearchSysCache()
452 * with arguments key1...key4. Retrieves only the portion of the tuple
453 * which is not variable-length.
455 * NOTE: we are assuming that non-variable-length fields in the system
456 * catalogs will always be defined!
458 * Returns 1L if a tuple was found, 0L if not.
461 SearchSysCacheStruct(int cacheId, /* cache selection code */
462 char *returnStruct, /* (preallocated!) */
470 if (!PointerIsValid(returnStruct))
472 elog(ERROR, "SearchSysCacheStruct: No receiving struct");
475 tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
476 if (!HeapTupleIsValid(tp))
478 memmove(returnStruct, (char *) GETSTRUCT(tp), cacheinfo[cacheId].size);
484 * SearchSysCacheGetAttribute--
485 * Returns the attribute corresponding to 'attributeNumber' for
486 * a given cached tuple.
488 * XXX This re-opens a relation, so this is slower.
490 * [callers all assume this returns a (struct varlena *). -ay 10/94]
493 SearchSysCacheGetAttribute(int cacheId,
494 AttrNumber attributeNumber,
503 int32 attributeLength,
506 Datum attributeValue;
509 tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
510 cacheName = cacheinfo[cacheId].name;
512 if (!HeapTupleIsValid(tp))
516 "SearchSysCacheGetAttribute: Lookup in %s(%d) failed",
518 #endif /* defined(CACHEDEBUG) */
522 relation = heap_openr(cacheName);
524 if (attributeNumber < 0 &&
525 attributeNumber > FirstLowInvalidHeapAttributeNumber)
527 attributeLength = heap_sysattrlen(attributeNumber);
528 attributeByValue = heap_sysattrbyval(attributeNumber);
530 else if (attributeNumber > 0 &&
531 attributeNumber <= relation->rd_rel->relnatts)
534 relation->rd_att->attrs[attributeNumber - 1]->attlen;
536 relation->rd_att->attrs[attributeNumber - 1]->attbyval;
541 "SearchSysCacheGetAttribute: Bad attr # %d in %s(%d)",
542 attributeNumber, cacheName, cacheId);
546 attributeValue = heap_getattr(tp,
548 RelationGetTupleDescriptor(relation),
555 * Used to be an elog(DEBUG, ...) here and a claim that it should
556 * be a FATAL error, I don't think either is warranted -mer 6/9/92
561 if (attributeByValue)
563 returnValue = (void *) attributeValue;
568 int size = (attributeLength < 0)
569 ? VARSIZE((struct varlena *) attributeValue) /* variable length */
570 : attributeLength; /* fixed length */
572 tmp = (char *) palloc(size);
573 memmove(tmp, (void *) attributeValue, size);
574 returnValue = (void *) tmp;
577 heap_close(relation);
578 return (returnValue);
582 * TypeDefaultRetrieve--
584 * Given a type OID, return the typdefault field associated with that
585 * type. The typdefault is returned as the car of a dotted pair which
586 * is passed to TypeDefaultRetrieve by the calling routine.
588 * Returns a fixnum for types which are passed by value and a ppreserve'd
589 * vectori for types which are not.
591 * [identical to get_typdefault, expecting a (struct varlena *) as ret val.
592 * some day, either of the functions should be removed -ay 10/94]
595 TypeDefaultRetrieve(Oid typId)
601 struct varlena *typDefault;
605 typeTuple = SearchSysCacheTuple(TYPOID,
606 ObjectIdGetDatum(typId),
609 if (!HeapTupleIsValid(typeTuple))
612 elog(DEBUG, "TypeDefaultRetrieve: Lookup in %s(%d) failed",
613 (*cacheinfo[TYPOID].name)->data, TYPOID);
614 #endif /* defined(CACHEDEBUG) */
618 type = (TypeTupleForm) GETSTRUCT(typeTuple);
619 typByVal = type->typbyval;
620 typLen = type->typlen;
622 typDefault = (struct varlena *)
623 SearchSysCacheGetAttribute(TYPOID,
624 Anum_pg_type_typdefault,
625 ObjectIdGetDatum(typId),
628 if (typDefault == (struct varlena *) NULL)
631 elog(DEBUG, "TypeDefaultRetrieve: No extractable typdefault",
632 (*cacheinfo[TYPOID].name)->data, TYPOID);
633 #endif /* defined(CACHEDEBUG) */
638 dataSize = VARSIZE(typDefault) - VARHDRSZ;
646 if (dataSize == typLen)
651 memmove((char *) &i8, VARDATA(typDefault), sizeof(int8));
655 memmove((char *) &i16, VARDATA(typDefault), sizeof(int16));
659 memmove((char *) &i32, VARDATA(typDefault), sizeof(int32));
662 returnValue = (void *) i32;
671 if ((typLen < 0 && dataSize < 0) || dataSize != typLen)
675 returnValue = (void *) palloc(VARSIZE(typDefault));
676 memmove((char *) returnValue,
678 (int) VARSIZE(typDefault));
682 return (returnValue);