syscache.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:15k
- /*-------------------------------------------------------------------------
- *
- * syscache.c
- * System cache management routines
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * $Header: /usr/local/cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.28.2.1 1999/08/02 05:25:01 scrappy Exp $
- *
- * NOTES
- * These routines allow the parser/planner/executor to perform
- * rapid lookups on the contents of the system catalogs.
- *
- * see catalog/syscache.h for a list of the cache id's
- *
- *-------------------------------------------------------------------------
- */
- #include "postgres.h"
- #include "access/heapam.h"
- #include "catalog/catname.h"
- #include "catalog/pg_aggregate.h"
- #include "catalog/pg_amop.h"
- #include "catalog/pg_group.h"
- #include "catalog/pg_index.h"
- #include "catalog/pg_inherits.h"
- #include "catalog/pg_language.h"
- #include "catalog/pg_listener.h"
- #include "catalog/pg_opclass.h"
- #include "catalog/pg_operator.h"
- #include "catalog/pg_proc.h"
- #include "catalog/pg_rewrite.h"
- #include "catalog/pg_shadow.h"
- #include "catalog/pg_type.h"
- #include "utils/catcache.h"
- extern bool AMI_OVERRIDE; /* XXX style */
- #include "utils/syscache.h"
- #include "catalog/indexing.h"
- typedef HeapTuple (*ScanFunc) ();
- /* ----------------
- * Warning: cacheinfo[] below is changed, then be sure and
- * update the magic constants in syscache.h!
- * ----------------
- */
- static struct cachedesc cacheinfo[] = {
- {AccessMethodOperatorRelationName, /* AMOPOPID */
- 3,
- {
- Anum_pg_amop_amopclaid,
- Anum_pg_amop_amopopr,
- Anum_pg_amop_amopid,
- 0
- },
- sizeof(FormData_pg_amop),
- NULL,
- (ScanFunc) NULL},
- {AccessMethodOperatorRelationName, /* AMOPSTRATEGY */
- 3,
- {
- Anum_pg_amop_amopid,
- Anum_pg_amop_amopclaid,
- Anum_pg_amop_amopstrategy,
- 0
- },
- sizeof(FormData_pg_amop),
- NULL,
- (ScanFunc) NULL},
- {AttributeRelationName, /* ATTNAME */
- 2,
- {
- Anum_pg_attribute_attrelid,
- Anum_pg_attribute_attname,
- 0,
- 0
- },
- ATTRIBUTE_TUPLE_SIZE,
- AttributeNameIndex,
- (ScanFunc) AttributeNameIndexScan},
- {AttributeRelationName, /* ATTNUM */
- 2,
- {
- Anum_pg_attribute_attrelid,
- Anum_pg_attribute_attnum,
- 0,
- 0
- },
- ATTRIBUTE_TUPLE_SIZE,
- AttributeNumIndex,
- (ScanFunc) AttributeNumIndexScan},
- {IndexRelationName, /* INDEXRELID */
- 1,
- {
- Anum_pg_index_indexrelid,
- 0,
- 0,
- 0
- },
- offsetof(FormData_pg_index, indpred),
- NULL,
- NULL},
- {LanguageRelationName, /* LANNAME */
- 1,
- {
- Anum_pg_language_lanname,
- 0,
- 0,
- 0
- },
- offsetof(FormData_pg_language, lancompiler),
- NULL,
- NULL},
- {OperatorRelationName, /* OPRNAME */
- 4,
- {
- Anum_pg_operator_oprname,
- Anum_pg_operator_oprleft,
- Anum_pg_operator_oprright,
- Anum_pg_operator_oprkind
- },
- sizeof(FormData_pg_operator),
- NULL,
- NULL},
- {OperatorRelationName, /* OPROID */
- 1,
- {
- ObjectIdAttributeNumber,
- 0,
- 0,
- 0
- },
- sizeof(FormData_pg_operator),
- NULL,
- (ScanFunc) NULL},
- {ProcedureRelationName, /* PRONAME */
- 3,
- {
- Anum_pg_proc_proname,
- Anum_pg_proc_pronargs,
- Anum_pg_proc_proargtypes,
- 0
- },
- offsetof(FormData_pg_proc, prosrc),
- ProcedureNameIndex,
- (ScanFunc) ProcedureNameIndexScan},
- {ProcedureRelationName, /* PROOID */
- 1,
- {
- ObjectIdAttributeNumber,
- 0,
- 0,
- 0
- },
- offsetof(FormData_pg_proc, prosrc),
- ProcedureOidIndex,
- (ScanFunc) ProcedureOidIndexScan},
- {RelationRelationName, /* RELNAME */
- 1,
- {
- Anum_pg_class_relname,
- 0,
- 0,
- 0
- },
- CLASS_TUPLE_SIZE,
- ClassNameIndex,
- (ScanFunc) ClassNameIndexScan},
- {RelationRelationName, /* RELOID */
- 1,
- {
- ObjectIdAttributeNumber,
- 0,
- 0,
- 0
- },
- CLASS_TUPLE_SIZE,
- ClassOidIndex,
- (ScanFunc) ClassOidIndexScan},
- {TypeRelationName, /* TYPNAME */
- 1,
- {
- Anum_pg_type_typname,
- 0,
- 0,
- 0
- },
- offsetof(FormData_pg_type, typalign) +sizeof(char),
- TypeNameIndex,
- TypeNameIndexScan},
- {TypeRelationName, /* TYPOID */
- 1,
- {
- ObjectIdAttributeNumber,
- 0,
- 0,
- 0
- },
- offsetof(FormData_pg_type, typalign) +sizeof(char),
- TypeOidIndex,
- TypeOidIndexScan},
- {AccessMethodRelationName, /* AMNAME */
- 1,
- {
- Anum_pg_am_amname,
- 0,
- 0,
- 0
- },
- sizeof(FormData_pg_am),
- NULL,
- NULL},
- {OperatorClassRelationName, /* CLANAME */
- 1,
- {
- Anum_pg_opclass_opcname,
- 0,
- 0,
- 0
- },
- sizeof(FormData_pg_opclass),
- NULL,
- NULL},
- {IndexRelationName, /* INDRELIDKEY *//* never used */
- 2,
- {
- Anum_pg_index_indrelid,
- Anum_pg_index_indkey,
- 0,
- 0
- },
- offsetof(FormData_pg_index, indpred),
- NULL,
- (ScanFunc) NULL},
- {InheritsRelationName, /* INHRELID */
- 2,
- {
- Anum_pg_inherits_inhrel,
- Anum_pg_inherits_inhseqno,
- 0,
- 0
- },
- sizeof(FormData_pg_inherits),
- NULL,
- (ScanFunc) NULL},
- {RewriteRelationName, /* RULOID */
- 1,
- {
- ObjectIdAttributeNumber,
- 0,
- 0,
- 0
- },
- offsetof(FormData_pg_rewrite, ev_qual),
- NULL,
- (ScanFunc) NULL},
- {AggregateRelationName, /* AGGNAME */
- 2,
- {
- Anum_pg_aggregate_aggname,
- Anum_pg_aggregate_aggbasetype,
- 0,
- 0
- },
- offsetof(FormData_pg_aggregate, agginitval1),
- NULL,
- (ScanFunc) NULL},
- {ListenerRelationName, /* LISTENREL */
- 2,
- {
- Anum_pg_listener_relname,
- Anum_pg_listener_pid,
- 0,
- 0
- },
- sizeof(FormData_pg_listener),
- NULL,
- (ScanFunc) NULL},
- {ShadowRelationName, /* USENAME */
- 1,
- {
- Anum_pg_shadow_usename,
- 0,
- 0,
- 0
- },
- sizeof(FormData_pg_shadow),
- NULL,
- (ScanFunc) NULL},
- {ShadowRelationName, /* USESYSID */
- 1,
- {
- Anum_pg_shadow_usesysid,
- 0,
- 0,
- 0
- },
- sizeof(FormData_pg_shadow),
- NULL,
- (ScanFunc) NULL},
- {GroupRelationName, /* GRONAME */
- 1,
- {
- Anum_pg_group_groname,
- 0,
- 0,
- 0
- },
- offsetof(FormData_pg_group, grolist[0]),
- NULL,
- (ScanFunc) NULL},
- {GroupRelationName, /* GROSYSID */
- 1,
- {
- Anum_pg_group_grosysid,
- 0,
- 0,
- 0
- },
- offsetof(FormData_pg_group, grolist[0]),
- NULL,
- (ScanFunc) NULL},
- {RewriteRelationName, /* REWRITENAME */
- 1,
- {
- Anum_pg_rewrite_rulename,
- 0,
- 0,
- 0
- },
- offsetof(FormData_pg_rewrite, ev_qual),
- NULL,
- (ScanFunc) NULL},
- {ProcedureRelationName, /* PROSRC */
- 1,
- {
- Anum_pg_proc_prosrc,
- 0,
- 0,
- 0
- },
- offsetof(FormData_pg_proc, prosrc),
- ProcedureSrcIndex,
- (ScanFunc) ProcedureSrcIndexScan},
- {OperatorClassRelationName, /* CLADEFTYPE */
- 1,
- {
- Anum_pg_opclass_opcdeftype,
- 0,
- 0,
- 0
- },
- sizeof(FormData_pg_opclass),
- NULL,
- (ScanFunc) NULL},
- {LanguageRelationName, /* LANOID */
- 1,
- {
- ObjectIdAttributeNumber,
- 0,
- 0,
- 0
- },
- offsetof(FormData_pg_language, lancompiler),
- NULL,
- NULL}
- };
- static struct catcache *SysCache[lengthof(cacheinfo)];
- static int32 SysCacheSize = lengthof(cacheinfo);
- /*
- * zerocaches
- *
- * Make sure the SysCache structure is zero'd.
- */
- void
- zerocaches()
- {
- MemSet((char *) SysCache, 0, SysCacheSize * sizeof(struct catcache *));
- }
- /*
- * Note:
- * This function was written because the initialized catalog caches
- * are used to determine which caches may contain tuples which need
- * to be invalidated in other backends.
- */
- void
- InitCatalogCache()
- {
- int cacheId; /* XXX type */
- if (!AMI_OVERRIDE)
- {
- for (cacheId = 0; cacheId < SysCacheSize; cacheId += 1)
- {
- Assert(!PointerIsValid((Pointer) SysCache[cacheId]));
- SysCache[cacheId] = InitSysCache(cacheinfo[cacheId].name,
- cacheinfo[cacheId].indname,
- cacheId,
- cacheinfo[cacheId].nkeys,
- cacheinfo[cacheId].key,
- cacheinfo[cacheId].iScanFunc);
- if (!PointerIsValid((char *) SysCache[cacheId]))
- {
- elog(ERROR,
- "InitCatalogCache: Can't init cache %s(%d)",
- cacheinfo[cacheId].name,
- cacheId);
- }
- }
- }
- }
- /*
- * SearchSysCacheTupleCopy
- *
- * This is like SearchSysCacheTuple, except it returns a copy of the tuple
- * that the user is required to pfree().
- */
- HeapTuple
- SearchSysCacheTupleCopy(int cacheId, /* cache selection code */
- Datum key1,
- Datum key2,
- Datum key3,
- Datum key4)
- {
- HeapTuple cachetup;
- cachetup = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
- if (PointerIsValid(cachetup))
- return heap_copytuple(cachetup);
- else
- return cachetup; /* NULL */
- }
- /*
- * SearchSysCacheTuple
- *
- * A layer on top of SearchSysCache that does the initialization and
- * key-setting for you.
- *
- * Returns the cache copy of the tuple if one is found, NULL if not.
- * The tuple is the 'cache' copy.
- *
- * XXX The tuple that is returned is NOT supposed to be pfree'd!
- */
- HeapTuple
- SearchSysCacheTuple(int cacheId,/* cache selection code */
- Datum key1,
- Datum key2,
- Datum key3,
- Datum key4)
- {
- HeapTuple tp;
- if (cacheId < 0 || cacheId >= SysCacheSize)
- {
- elog(ERROR, "SearchSysCacheTuple: Bad cache id %d", cacheId);
- return (HeapTuple) NULL;
- }
- Assert(AMI_OVERRIDE || PointerIsValid(SysCache[cacheId]));
- if (!PointerIsValid(SysCache[cacheId]))
- {
- SysCache[cacheId] = InitSysCache(cacheinfo[cacheId].name,
- cacheinfo[cacheId].indname,
- cacheId,
- cacheinfo[cacheId].nkeys,
- cacheinfo[cacheId].key,
- cacheinfo[cacheId].iScanFunc);
- if (!PointerIsValid(SysCache[cacheId]))
- elog(ERROR,
- "InitCatalogCache: Can't init cache %s(%d)",
- cacheinfo[cacheId].name,
- cacheId);
- }
- tp = SearchSysCache(SysCache[cacheId], key1, key2, key3, key4);
- if (!HeapTupleIsValid(tp))
- {
- #ifdef CACHEDEBUG
- elog(DEBUG,
- "SearchSysCacheTuple: Search %s(%d) %d %d %d %d failed",
- cacheinfo[cacheId].name,
- cacheId, key1, key2, key3, key4);
- #endif
- return (HeapTuple) NULL;
- }
- return tp;
- }
- /*
- * SearchSysCacheStruct
- * Fills 's' with the information retrieved by calling SearchSysCache()
- * with arguments key1...key4. Retrieves only the portion of the tuple
- * which is not variable-length.
- *
- * NOTE: we are assuming that non-variable-length fields in the system
- * catalogs will always be defined!
- *
- * Returns 1L if a tuple was found, 0L if not.
- */
- int32
- SearchSysCacheStruct(int cacheId, /* cache selection code */
- char *returnStruct, /* (preallocated!) */
- Datum key1,
- Datum key2,
- Datum key3,
- Datum key4)
- {
- HeapTuple tp;
- if (!PointerIsValid(returnStruct))
- {
- elog(ERROR, "SearchSysCacheStruct: No receiving struct");
- return 0;
- }
- tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
- if (!HeapTupleIsValid(tp))
- return 0;
- memcpy(returnStruct, (char *) GETSTRUCT(tp), cacheinfo[cacheId].size);
- return 1;
- }
- /*
- * SearchSysCacheGetAttribute
- * Returns the attribute corresponding to 'attributeNumber' for
- * a given cached tuple. This routine usually needs to be used for
- * attributes that might be NULL or might be at a variable offset
- * in the tuple.
- *
- * XXX This re-opens the relation, so this is slower than just pulling
- * fixed-location fields out of the struct returned by SearchSysCacheTuple.
- *
- * [callers all assume this returns a (struct varlena *). -ay 10/94]
- */
- void *
- SearchSysCacheGetAttribute(int cacheId,
- AttrNumber attributeNumber,
- Datum key1,
- Datum key2,
- Datum key3,
- Datum key4)
- {
- HeapTuple tp;
- char *cacheName;
- Relation relation;
- int32 attributeLength,
- attributeByValue;
- bool isNull;
- Datum attributeValue;
- void *returnValue;
- tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
- cacheName = cacheinfo[cacheId].name;
- if (!HeapTupleIsValid(tp))
- {
- #ifdef CACHEDEBUG
- elog(DEBUG,
- "SearchSysCacheGetAttribute: Lookup in %s(%d) failed",
- cacheName, cacheId);
- #endif /* defined(CACHEDEBUG) */
- return NULL;
- }
- relation = heap_openr(cacheName);
- if (attributeNumber < 0 &&
- attributeNumber > FirstLowInvalidHeapAttributeNumber)
- {
- attributeLength = heap_sysattrlen(attributeNumber);
- attributeByValue = heap_sysattrbyval(attributeNumber);
- }
- else if (attributeNumber > 0 &&
- attributeNumber <= relation->rd_rel->relnatts)
- {
- attributeLength = relation->rd_att->attrs[attributeNumber - 1]->attlen;
- attributeByValue = relation->rd_att->attrs[attributeNumber - 1]->attbyval;
- }
- else
- {
- elog(ERROR,
- "SearchSysCacheGetAttribute: Bad attr # %d in %s(%d)",
- attributeNumber, cacheName, cacheId);
- return NULL;
- }
- attributeValue = heap_getattr(tp,
- attributeNumber,
- RelationGetDescr(relation),
- &isNull);
- if (isNull)
- {
- /*
- * Used to be an elog(DEBUG, ...) here and a claim that it should
- * be a FATAL error, I don't think either is warranted -mer 6/9/92
- */
- return NULL;
- }
- if (attributeByValue)
- returnValue = (void *) attributeValue;
- else
- {
- char *tmp;
- int size = (attributeLength < 0)
- ? VARSIZE((struct varlena *) attributeValue) /* variable length */
- : attributeLength; /* fixed length */
- tmp = (char *) palloc(size);
- memcpy(tmp, (void *) attributeValue, size);
- returnValue = (void *) tmp;
- }
- heap_close(relation);
- return returnValue;
- }
- /*
- * TypeDefaultRetrieve
- *
- * Given a type OID, return the typdefault field associated with that
- * type. The result is a Datum, and points to palloc'd storage for
- * non-pass-by-value types.
- *
- * [identical to get_typdefault, expecting a (struct varlena *) as ret val.
- * some day, either of the functions should be removed -ay 10/94]
- */
- void *
- TypeDefaultRetrieve(Oid typId)
- {
- struct varlena *typDefault;
- int32 dataSize;
- HeapTuple typeTuple;
- Form_pg_type type;
- int32 typByVal,
- typLen;
- void *returnValue;
- /*
- * First, see if there is a non-null typdefault field (usually there isn't)
- */
- typDefault = (struct varlena *)
- SearchSysCacheGetAttribute(TYPOID,
- Anum_pg_type_typdefault,
- ObjectIdGetDatum(typId),
- 0, 0, 0);
- if (typDefault == NULL)
- {
- #ifdef CACHEDEBUG
- elog(DEBUG, "TypeDefaultRetrieve: No extractable typdefault in %s(%d)",
- cacheinfo[TYPOID].name, TYPOID);
- #endif /* defined(CACHEDEBUG) */
- return NULL;
- }
- dataSize = VARSIZE(typDefault) - VARHDRSZ;
- /*
- * Need the type's length and byVal fields.
- *
- * XXX silly to repeat the syscache search that SearchSysCacheGetAttribute
- * just did --- but at present this path isn't taken often enough to
- * make it worth fixing.
- */
- typeTuple = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(typId),
- 0, 0, 0);
- if (!HeapTupleIsValid(typeTuple))
- {
- /* should never get here, really... */
- #ifdef CACHEDEBUG
- elog(DEBUG, "TypeDefaultRetrieve: Lookup in %s(%d) failed",
- cacheinfo[TYPOID].name, TYPOID);
- #endif /* defined(CACHEDEBUG) */
- return NULL;
- }
- type = (Form_pg_type) GETSTRUCT(typeTuple);
- typLen = type->typlen;
- typByVal = type->typbyval;
- if (typByVal)
- {
- int8 i8;
- int16 i16;
- int32 i32 = 0;
- if (dataSize == typLen)
- {
- switch (typLen)
- {
- case sizeof(int8):
- memcpy((char *) &i8, VARDATA(typDefault), sizeof(int8));
- i32 = i8;
- break;
- case sizeof(int16):
- memcpy((char *) &i16, VARDATA(typDefault), sizeof(int16));
- i32 = i16;
- break;
- case sizeof(int32):
- memcpy((char *) &i32, VARDATA(typDefault), sizeof(int32));
- break;
- }
- returnValue = (void *) i32;
- }
- else
- returnValue = NULL;
- }
- else
- {
- if ((typLen < 0 && dataSize < 0) || dataSize != typLen)
- returnValue = NULL;
- else
- {
- returnValue = (void *) palloc(VARSIZE(typDefault));
- memcpy((char *) returnValue,
- (char *) typDefault,
- (int) VARSIZE(typDefault));
- }
- }
- return returnValue;
- }