Commit 27fee810 authored by Tom Lane's avatar Tom Lane

Replace SearchSysCacheGetAttribute with SysCacheGetAttr, which fetches

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.
parent 1161077e
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -587,9 +587,6 @@ getattproperties(Oid relid, AttrNumber attnum, ...@@ -587,9 +587,6 @@ getattproperties(Oid relid, AttrNumber attnum,
* commonval, loval, hival are returned as Datums holding the internal * commonval, loval, hival are returned as Datums holding the internal
* representation of the values. (Note that these should be pfree'd * representation of the values. (Note that these should be pfree'd
* after use if the data type is not by-value.) * 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 static bool
getattstatistics(Oid relid, AttrNumber attnum, Oid opid, Oid typid, getattstatistics(Oid relid, AttrNumber attnum, Oid opid, Oid typid,
...@@ -600,29 +597,26 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid opid, Oid typid, ...@@ -600,29 +597,26 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid opid, Oid typid,
Datum *loval, Datum *loval,
Datum *hival) Datum *hival)
{ {
Relation rel;
bool isnull;
HeapTuple tuple; HeapTuple tuple;
HeapTuple typeTuple; HeapTuple typeTuple;
FmgrInfo inputproc; FmgrInfo inputproc;
Oid typelem; 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, tuple = SearchSysCacheTuple(STATRELID,
ObjectIdGetDatum(relid), ObjectIdGetDatum(relid),
Int16GetDatum((int16) attnum), Int16GetDatum((int16) attnum),
opid, 0); opid,
0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
{ {
/* no such stats entry */ /* no such stats entry */
heap_close(rel, AccessShareLock);
return false; 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) if (nullfrac)
*nullfrac = ((Form_pg_statistic) GETSTRUCT(tuple))->stanullfrac; *nullfrac = ((Form_pg_statistic) GETSTRUCT(tuple))->stanullfrac;
if (commonfrac) if (commonfrac)
...@@ -639,14 +633,13 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid opid, Oid typid, ...@@ -639,14 +633,13 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid opid, Oid typid,
typelem = ((Form_pg_type) GETSTRUCT(typeTuple))->typelem; typelem = ((Form_pg_type) GETSTRUCT(typeTuple))->typelem;
/* Values are variable-length fields, so cannot access as struct fields. /* 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) if (commonval)
{ {
text *val = (text *) heap_getattr(tuple, text *val = (text *) SysCacheGetAttr(STATRELID, tuple,
Anum_pg_statistic_stacommonval, Anum_pg_statistic_stacommonval,
RelationGetDescr(rel), &isnull);
&isnull);
if (isnull) if (isnull)
{ {
elog(DEBUG, "getattstatistics: stacommonval is null"); elog(DEBUG, "getattstatistics: stacommonval is null");
...@@ -663,10 +656,9 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid opid, Oid typid, ...@@ -663,10 +656,9 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid opid, Oid typid,
if (loval) if (loval)
{ {
text *val = (text *) heap_getattr(tuple, text *val = (text *) SysCacheGetAttr(STATRELID, tuple,
Anum_pg_statistic_staloval, Anum_pg_statistic_staloval,
RelationGetDescr(rel), &isnull);
&isnull);
if (isnull) if (isnull)
{ {
elog(DEBUG, "getattstatistics: staloval is null"); elog(DEBUG, "getattstatistics: staloval is null");
...@@ -683,10 +675,9 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid opid, Oid typid, ...@@ -683,10 +675,9 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid opid, Oid typid,
if (hival) if (hival)
{ {
text *val = (text *) heap_getattr(tuple, text *val = (text *) SysCacheGetAttr(STATRELID, tuple,
Anum_pg_statistic_stahival, Anum_pg_statistic_stahival,
RelationGetDescr(rel), &isnull);
&isnull);
if (isnull) if (isnull)
{ {
elog(DEBUG, "getattstatistics: stahival is null"); elog(DEBUG, "getattstatistics: stahival is null");
...@@ -701,7 +692,6 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid opid, Oid typid, ...@@ -701,7 +692,6 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid opid, Oid typid,
} }
} }
heap_close(rel, AccessShareLock);
return true; return true;
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -74,13 +74,12 @@ init_fcache(Oid foid, ...@@ -74,13 +74,12 @@ init_fcache(Oid foid,
Form_pg_proc procedureStruct; Form_pg_proc procedureStruct;
Form_pg_type typeStruct; Form_pg_type typeStruct;
FunctionCachePtr retval; FunctionCachePtr retval;
text *tmp;
int nargs; int nargs;
text *tmp;
bool isNull;
/* ---------------- /* ----------------
* get the procedure tuple corresponding to the given * get the procedure tuple corresponding to the given functionOid
* functionOid. If this fails, returnValue has been
* pre-initialized to "null" so we just return it.
* ---------------- * ----------------
*/ */
retval = (FunctionCachePtr) palloc(sizeof(FunctionCache)); retval = (FunctionCachePtr) palloc(sizeof(FunctionCache));
...@@ -94,20 +93,13 @@ init_fcache(Oid foid, ...@@ -94,20 +93,13 @@ init_fcache(Oid foid,
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(procedureTuple)) if (!HeapTupleIsValid(procedureTuple))
elog(ERROR, elog(ERROR, "init_fcache: Cache lookup failed for procedure %u",
"init_fcache: %s %u", foid);
"Cache lookup failed for procedure", foid);
/* ----------------
* get the return type from the procedure tuple
* ----------------
*/
procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple); procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
/* ---------------- /* ----------------
* get the type tuple corresponding to the return type * get the return type from the procedure tuple
* If this fails, returnValue has been pre-initialized
* to "null" so we just return it.
* ---------------- * ----------------
*/ */
typeTuple = SearchSysCacheTuple(TYPEOID, typeTuple = SearchSysCacheTuple(TYPEOID,
...@@ -115,27 +107,24 @@ init_fcache(Oid foid, ...@@ -115,27 +107,24 @@ init_fcache(Oid foid,
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(typeTuple)) if (!HeapTupleIsValid(typeTuple))
elog(ERROR, elog(ERROR, "init_fcache: Cache lookup failed for type %u",
"init_fcache: %s %u", procedureStruct->prorettype);
"Cache lookup failed for type",
(procedureStruct)->prorettype); typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
/* ---------------- /* ----------------
* get the type length and by-value from the type tuple and * get the type length and by-value from the type tuple and
* save the information in our one element cache. * 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 */ /* The return type is not a relation, so just use byval */
retval->typbyval = (typeStruct)->typbyval ? true : false; retval->typbyval = typeStruct->typbyval;
} }
else else
{ {
/* /*
* This is a hack. We assume here that any function returning a * This is a hack. We assume here that any function returning a
* relation returns it by reference. This needs to be fixed. * relation returns it by reference. This needs to be fixed.
...@@ -147,7 +136,7 @@ init_fcache(Oid foid, ...@@ -147,7 +136,7 @@ init_fcache(Oid foid,
retval->func_state = (char *) NULL; retval->func_state = (char *) NULL;
retval->setArg = NULL; retval->setArg = NULL;
retval->hasSetArg = false; retval->hasSetArg = false;
retval->oneResult = !procedureStruct->proretset; retval->oneResult = ! procedureStruct->proretset;
retval->istrusted = procedureStruct->proistrusted; retval->istrusted = procedureStruct->proistrusted;
/* /*
...@@ -157,8 +146,8 @@ init_fcache(Oid foid, ...@@ -157,8 +146,8 @@ init_fcache(Oid foid,
* allocated by the executor (i.e. slots and tuples) is freed. * allocated by the executor (i.e. slots and tuples) is freed.
*/ */
if ((retval->language == SQLlanguageId) && if ((retval->language == SQLlanguageId) &&
(retval->oneResult) && retval->oneResult &&
!(retval->typbyval)) ! retval->typbyval)
{ {
Form_pg_class relationStruct; Form_pg_class relationStruct;
HeapTuple relationTuple; HeapTuple relationTuple;
...@@ -198,7 +187,7 @@ init_fcache(Oid foid, ...@@ -198,7 +187,7 @@ init_fcache(Oid foid,
{ {
Oid *argTypes; Oid *argTypes;
retval->nullVect = (bool *) palloc((retval->nargs) * sizeof(bool)); retval->nullVect = (bool *) palloc(retval->nargs * sizeof(bool));
if (retval->language == SQLlanguageId) if (retval->language == SQLlanguageId)
{ {
...@@ -230,43 +219,36 @@ init_fcache(Oid foid, ...@@ -230,43 +219,36 @@ init_fcache(Oid foid,
retval->nullVect = (BoolPtr) NULL; 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) 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; retval->bin = (char *) NULL;
} }
else else
{ {
retval->src = (char *) NULL;
/*
* I'm not sure that we even need to do this at all.
*/
/*
* We do for untrusted functions.
*/
if (procedureStruct->proistrusted) if (procedureStruct->proistrusted)
retval->bin = (char *) NULL; retval->bin = (char *) NULL;
else else
{ {
tmp = (text *) tmp = (text *) SysCacheGetAttr(PROCOID,
SearchSysCacheGetAttribute(PROCOID, procedureTuple,
Anum_pg_proc_probin, Anum_pg_proc_probin,
ObjectIdGetDatum(foid), &isNull);
0, 0, 0); if (isNull)
elog(ERROR, "init_fcache: null probin for procedure %u",
foid);
retval->bin = textout(tmp); retval->bin = textout(tmp);
} }
retval->src = (char *) NULL;
} }
if (retval->language != SQLlanguageId) if (retval->language != SQLlanguageId)
{ {
fmgr_info(foid, &(retval->func)); fmgr_info(foid, &(retval->func));
...@@ -275,7 +257,6 @@ init_fcache(Oid foid, ...@@ -275,7 +257,6 @@ init_fcache(Oid foid,
else else
retval->func.fn_addr = (func_ptr) NULL; retval->func.fn_addr = (func_ptr) NULL;
return retval; return retval;
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 * NOTES
* Eventually, the index information should go through here, too. * Eventually, the index information should go through here, too.
...@@ -617,35 +617,15 @@ get_typalign(Oid typid) ...@@ -617,35 +617,15 @@ get_typalign(Oid typid)
Datum Datum
get_typdefault(Oid typid) get_typdefault(Oid typid)
{ {
struct varlena *typDefault;
int32 dataSize;
HeapTuple typeTuple; HeapTuple typeTuple;
Form_pg_type type; Form_pg_type type;
struct varlena *typDefault;
bool isNull;
int32 dataSize;
int32 typLen; int32 typLen;
bool typByVal; bool typByVal;
Datum returnValue; 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, typeTuple = SearchSysCacheTuple(TYPEOID,
ObjectIdGetDatum(typid), ObjectIdGetDatum(typid),
0, 0, 0); 0, 0, 0);
...@@ -654,6 +634,22 @@ get_typdefault(Oid typid) ...@@ -654,6 +634,22 @@ get_typdefault(Oid typid)
elog(ERROR, "get_typdefault: failed to lookup type %u", typid); elog(ERROR, "get_typdefault: failed to lookup type %u", typid);
type = (Form_pg_type) GETSTRUCT(typeTuple); 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; typLen = type->typlen;
typByVal = type->typbyval; typByVal = type->typbyval;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* These routines allow the parser/planner/executor to perform * These routines allow the parser/planner/executor to perform
...@@ -535,140 +535,42 @@ SearchSysCacheTuple(int cacheId,/* cache selection code */ ...@@ -535,140 +535,42 @@ SearchSysCacheTuple(int cacheId,/* cache selection code */
return tp; 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 * SysCacheGetAttr
* Returns the attribute corresponding to 'attributeNumber' for *
* a given cached tuple. This routine usually needs to be used for * Given a tuple previously fetched by SearchSysCacheTuple() or
* attributes that might be NULL or might be at a variable offset * SearchSysCacheTupleCopy(), extract a specific attribute.
* in the tuple.
* *
* XXX This re-opens the relation, so this is slower than just pulling * This is equivalent to using heap_getattr() on a tuple fetched
* fixed-location fields out of the struct returned by SearchSysCacheTuple. * 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 * Datum
SearchSysCacheGetAttribute(int cacheId, SysCacheGetAttr(int cacheId, HeapTuple tup,
AttrNumber attributeNumber, AttrNumber attributeNumber,
Datum key1, bool *isnull)
Datum key2,
Datum key3,
Datum key4)
{ {
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 * We just need to get the TupleDesc out of the cache entry,
* events --- we don't want the tuple found in the cache to be * and then we can apply heap_getattr(). We expect that the cache
* invalidated out from under us. * control data is currently valid --- if the caller just fetched
* the tuple, then it should be.
*/ */
cacheName = cacheinfo[cacheId].name; if (cacheId < 0 || cacheId >= SysCacheSize)
relation = heap_openr(cacheName, AccessShareLock); elog(ERROR, "SysCacheGetAttr: Bad cache id %d", cacheId);
if (! PointerIsValid(SysCache[cacheId]) ||
tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4); SysCache[cacheId]->relationId == InvalidOid ||
! PointerIsValid(SysCache[cacheId]->cc_tupdesc))
if (!HeapTupleIsValid(tp)) elog(ERROR, "SysCacheGetAttr: missing cache data for id %d", cacheId);
{
heap_close(relation, AccessShareLock); return heap_getattr(tup, attributeNumber,
#ifdef CACHEDEBUG SysCache[cacheId]->cc_tupdesc,
elog(DEBUG, isnull);
"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;
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -81,10 +81,8 @@ extern HeapTuple SearchSysCacheTupleCopy(int cacheId, ...@@ -81,10 +81,8 @@ extern HeapTuple SearchSysCacheTupleCopy(int cacheId,
Datum key1, Datum key2, Datum key3, Datum key4); Datum key1, Datum key2, Datum key3, Datum key4);
extern HeapTuple SearchSysCacheTuple(int cacheId, extern HeapTuple SearchSysCacheTuple(int cacheId,
Datum key1, Datum key2, Datum key3, Datum key4); Datum key1, Datum key2, Datum key3, Datum key4);
extern int32 SearchSysCacheStruct(int cacheId, char *returnStruct, extern Datum SysCacheGetAttr(int cacheId, HeapTuple tup,
Datum key1, Datum key2, Datum key3, Datum key4); AttrNumber attributeNumber,
extern void *SearchSysCacheGetAttribute(int cacheId, bool *isnull);
AttrNumber attributeNumber,
Datum key1, Datum key2, Datum key3, Datum key4);
#endif /* SYSCACHE_H */ #endif /* SYSCACHE_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment