an attribute of a tuple previously fetched with SearchSysCacheTuple.
This avoids a lot of redundant cache lookups, particularly in selfuncs.c.
Also, remove SearchSysCacheStruct, which was unused and grotty.
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.50 2000/01/23 02:06:56 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.51 2000/01/23 03:43:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* commonval, loval, hival are returned as Datums holding the internal
* representation of the values. (Note that these should be pfree'd
* after use if the data type is not by-value.)
- *
- * XXX currently, this does a linear search of pg_statistic because there
- * is no index nor syscache for pg_statistic. FIX THIS!
*/
static bool
getattstatistics(Oid relid, AttrNumber attnum, Oid opid, Oid typid,
Datum *loval,
Datum *hival)
{
- Relation rel;
- bool isnull;
HeapTuple tuple;
HeapTuple typeTuple;
FmgrInfo inputproc;
Oid typelem;
+ bool isnull;
- rel = heap_openr(StatisticRelationName, AccessShareLock);
-
+ /* We assume that there will only be one entry in pg_statistic
+ * for the given rel/att. Someday, VACUUM might store more than one...
+ */
tuple = SearchSysCacheTuple(STATRELID,
- ObjectIdGetDatum(relid),
- Int16GetDatum((int16) attnum),
- opid, 0);
+ ObjectIdGetDatum(relid),
+ Int16GetDatum((int16) attnum),
+ opid,
+ 0);
if (!HeapTupleIsValid(tuple))
{
/* no such stats entry */
- heap_close(rel, AccessShareLock);
return false;
}
- /* We assume that there will only be one entry in pg_statistic
- * for the given rel/att. Someday, VACUUM might store more than one...
- */
if (nullfrac)
*nullfrac = ((Form_pg_statistic) GETSTRUCT(tuple))->stanullfrac;
if (commonfrac)
typelem = ((Form_pg_type) GETSTRUCT(typeTuple))->typelem;
/* Values are variable-length fields, so cannot access as struct fields.
- * Must do it the hard way with heap_getattr.
+ * Must do it the hard way with SysCacheGetAttr.
*/
if (commonval)
{
- text *val = (text *) heap_getattr(tuple,
- Anum_pg_statistic_stacommonval,
- RelationGetDescr(rel),
- &isnull);
+ text *val = (text *) SysCacheGetAttr(STATRELID, tuple,
+ Anum_pg_statistic_stacommonval,
+ &isnull);
if (isnull)
{
elog(DEBUG, "getattstatistics: stacommonval is null");
if (loval)
{
- text *val = (text *) heap_getattr(tuple,
- Anum_pg_statistic_staloval,
- RelationGetDescr(rel),
- &isnull);
+ text *val = (text *) SysCacheGetAttr(STATRELID, tuple,
+ Anum_pg_statistic_staloval,
+ &isnull);
if (isnull)
{
elog(DEBUG, "getattstatistics: staloval is null");
if (hival)
{
- text *val = (text *) heap_getattr(tuple,
- Anum_pg_statistic_stahival,
- RelationGetDescr(rel),
- &isnull);
+ text *val = (text *) SysCacheGetAttr(STATRELID, tuple,
+ Anum_pg_statistic_stahival,
+ &isnull);
if (isnull)
{
elog(DEBUG, "getattstatistics: stahival is null");
}
}
- heap_close(rel, AccessShareLock);
return true;
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.27 1999/11/22 17:56:32 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.28 2000/01/23 03:43:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
Form_pg_proc procedureStruct;
Form_pg_type typeStruct;
FunctionCachePtr retval;
- text *tmp;
int nargs;
+ text *tmp;
+ bool isNull;
/* ----------------
- * get the procedure tuple corresponding to the given
- * functionOid. If this fails, returnValue has been
- * pre-initialized to "null" so we just return it.
+ * get the procedure tuple corresponding to the given functionOid
* ----------------
*/
retval = (FunctionCachePtr) palloc(sizeof(FunctionCache));
0, 0, 0);
if (!HeapTupleIsValid(procedureTuple))
- elog(ERROR,
- "init_fcache: %s %u",
- "Cache lookup failed for procedure", foid);
+ elog(ERROR, "init_fcache: Cache lookup failed for procedure %u",
+ foid);
- /* ----------------
- * get the return type from the procedure tuple
- * ----------------
- */
procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
/* ----------------
- * get the type tuple corresponding to the return type
- * If this fails, returnValue has been pre-initialized
- * to "null" so we just return it.
+ * get the return type from the procedure tuple
* ----------------
*/
typeTuple = SearchSysCacheTuple(TYPEOID,
0, 0, 0);
if (!HeapTupleIsValid(typeTuple))
- elog(ERROR,
- "init_fcache: %s %u",
- "Cache lookup failed for type",
- (procedureStruct)->prorettype);
+ elog(ERROR, "init_fcache: Cache lookup failed for type %u",
+ procedureStruct->prorettype);
+
+ typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
/* ----------------
* get the type length and by-value from the type tuple and
* save the information in our one element cache.
* ----------------
*/
- typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
-
- retval->typlen = (typeStruct)->typlen;
- if ((typeStruct)->typrelid == InvalidOid)
+ retval->typlen = typeStruct->typlen;
+ if (typeStruct->typrelid == InvalidOid)
{
/* The return type is not a relation, so just use byval */
- retval->typbyval = (typeStruct)->typbyval ? true : false;
+ retval->typbyval = typeStruct->typbyval;
}
else
{
-
/*
* This is a hack. We assume here that any function returning a
* relation returns it by reference. This needs to be fixed.
retval->func_state = (char *) NULL;
retval->setArg = NULL;
retval->hasSetArg = false;
- retval->oneResult = !procedureStruct->proretset;
+ retval->oneResult = ! procedureStruct->proretset;
retval->istrusted = procedureStruct->proistrusted;
/*
* allocated by the executor (i.e. slots and tuples) is freed.
*/
if ((retval->language == SQLlanguageId) &&
- (retval->oneResult) &&
- !(retval->typbyval))
+ retval->oneResult &&
+ ! retval->typbyval)
{
Form_pg_class relationStruct;
HeapTuple relationTuple;
{
Oid *argTypes;
- retval->nullVect = (bool *) palloc((retval->nargs) * sizeof(bool));
+ retval->nullVect = (bool *) palloc(retval->nargs * sizeof(bool));
if (retval->language == SQLlanguageId)
{
retval->nullVect = (BoolPtr) NULL;
}
- /*
- * XXX this is the first varlena in the struct. If the order changes
- * for some reason this will fail.
- */
if (procedureStruct->prolang == SQLlanguageId)
{
- retval->src = textout(&(procedureStruct->prosrc));
+ tmp = (text *) SysCacheGetAttr(PROCOID,
+ procedureTuple,
+ Anum_pg_proc_prosrc,
+ &isNull);
+ if (isNull)
+ elog(ERROR, "init_fcache: null prosrc for procedure %u",
+ foid);
+ retval->src = textout(tmp);
retval->bin = (char *) NULL;
}
else
{
-
- /*
- * I'm not sure that we even need to do this at all.
- */
-
- /*
- * We do for untrusted functions.
- */
-
+ retval->src = (char *) NULL;
if (procedureStruct->proistrusted)
retval->bin = (char *) NULL;
else
{
- tmp = (text *)
- SearchSysCacheGetAttribute(PROCOID,
+ tmp = (text *) SysCacheGetAttr(PROCOID,
+ procedureTuple,
Anum_pg_proc_probin,
- ObjectIdGetDatum(foid),
- 0, 0, 0);
+ &isNull);
+ if (isNull)
+ elog(ERROR, "init_fcache: null probin for procedure %u",
+ foid);
retval->bin = textout(tmp);
}
- retval->src = (char *) NULL;
}
-
-
-
if (retval->language != SQLlanguageId)
{
fmgr_info(foid, &(retval->func));
else
retval->func.fn_addr = (func_ptr) NULL;
-
return retval;
}
* Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.37 1999/12/31 03:18:43 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.38 2000/01/23 03:43:24 tgl Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
Datum
get_typdefault(Oid typid)
{
- struct varlena *typDefault;
- int32 dataSize;
HeapTuple typeTuple;
Form_pg_type type;
+ struct varlena *typDefault;
+ bool isNull;
+ int32 dataSize;
int32 typLen;
bool typByVal;
Datum returnValue;
- /*
- * First, see if there is a non-null typdefault field (usually there isn't)
- */
- typDefault = (struct varlena *)
- SearchSysCacheGetAttribute(TYPEOID,
- Anum_pg_type_typdefault,
- ObjectIdGetDatum(typid),
- 0, 0, 0);
-
- if (typDefault == NULL)
- return PointerGetDatum(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(TYPEOID,
ObjectIdGetDatum(typid),
0, 0, 0);
elog(ERROR, "get_typdefault: failed to lookup type %u", typid);
type = (Form_pg_type) GETSTRUCT(typeTuple);
+
+ /*
+ * First, see if there is a non-null typdefault field (usually there isn't)
+ */
+ typDefault = (struct varlena *) SysCacheGetAttr(TYPEOID,
+ typeTuple,
+ Anum_pg_type_typdefault,
+ &isNull);
+
+ if (isNull)
+ return PointerGetDatum(NULL);
+
+ /*
+ * Otherwise, extract/copy the value.
+ */
+ dataSize = VARSIZE(typDefault) - VARHDRSZ;
typLen = type->typlen;
typByVal = type->typbyval;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.44 1999/11/24 17:09:27 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.45 2000/01/23 03:43:24 tgl Exp $
*
* NOTES
* These routines allow the parser/planner/executor to perform
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.
+ * SysCacheGetAttr
+ *
+ * Given a tuple previously fetched by SearchSysCacheTuple() or
+ * SearchSysCacheTupleCopy(), extract a specific attribute.
*
- * XXX This re-opens the relation, so this is slower than just pulling
- * fixed-location fields out of the struct returned by SearchSysCacheTuple.
+ * This is equivalent to using heap_getattr() on a tuple fetched
+ * from a non-cached relation. Usually, this is only used for attributes
+ * that could be NULL or variable length; the fixed-size attributes in
+ * a system table are accessed just by mapping the tuple onto the C struct
+ * declarations from include/catalog/.
*
- * [callers all assume this returns a (struct varlena *). -ay 10/94]
+ * As with heap_getattr(), if the attribute is of a pass-by-reference type
+ * then a pointer into the tuple data area is returned --- the caller must
+ * not modify or pfree the datum!
*/
-void *
-SearchSysCacheGetAttribute(int cacheId,
- AttrNumber attributeNumber,
- Datum key1,
- Datum key2,
- Datum key3,
- Datum key4)
+Datum
+SysCacheGetAttr(int cacheId, HeapTuple tup,
+ AttrNumber attributeNumber,
+ bool *isnull)
{
- HeapTuple tp;
- char *cacheName;
- Relation relation;
- int32 attributeLength,
- attributeByValue;
- bool isNull;
- Datum attributeValue;
- void *returnValue;
-
/*
- * Open the relation first, to ensure we are in sync with SI inval
- * events --- we don't want the tuple found in the cache to be
- * invalidated out from under us.
+ * We just need to get the TupleDesc out of the cache entry,
+ * and then we can apply heap_getattr(). We expect that the cache
+ * control data is currently valid --- if the caller just fetched
+ * the tuple, then it should be.
*/
- cacheName = cacheinfo[cacheId].name;
- relation = heap_openr(cacheName, AccessShareLock);
-
- tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
-
- if (!HeapTupleIsValid(tp))
- {
- heap_close(relation, AccessShareLock);
-#ifdef CACHEDEBUG
- elog(DEBUG,
- "SearchSysCacheGetAttribute: Lookup in %s(%d) failed",
- cacheName, cacheId);
-#endif /* defined(CACHEDEBUG) */
- return NULL;
- }
-
- 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
- {
- heap_close(relation, AccessShareLock);
- 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
- */
- heap_close(relation, AccessShareLock);
- 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, AccessShareLock);
- return returnValue;
+ if (cacheId < 0 || cacheId >= SysCacheSize)
+ elog(ERROR, "SysCacheGetAttr: Bad cache id %d", cacheId);
+ if (! PointerIsValid(SysCache[cacheId]) ||
+ SysCache[cacheId]->relationId == InvalidOid ||
+ ! PointerIsValid(SysCache[cacheId]->cc_tupdesc))
+ elog(ERROR, "SysCacheGetAttr: missing cache data for id %d", cacheId);
+
+ return heap_getattr(tup, attributeNumber,
+ SysCache[cacheId]->cc_tupdesc,
+ isnull);
}
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: syscache.h,v 1.22 1999/11/24 16:52:50 momjian Exp $
+ * $Id: syscache.h,v 1.23 2000/01/23 03:43:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
Datum key1, Datum key2, Datum key3, Datum key4);
extern HeapTuple SearchSysCacheTuple(int cacheId,
Datum key1, Datum key2, Datum key3, Datum key4);
-extern int32 SearchSysCacheStruct(int cacheId, char *returnStruct,
- Datum key1, Datum key2, Datum key3, Datum key4);
-extern void *SearchSysCacheGetAttribute(int cacheId,
- AttrNumber attributeNumber,
- Datum key1, Datum key2, Datum key3, Datum key4);
+extern Datum SysCacheGetAttr(int cacheId, HeapTuple tup,
+ AttrNumber attributeNumber,
+ bool *isnull);
#endif /* SYSCACHE_H */