Skip to content
Snippets Groups Projects
Commit 27fee810 authored by Tom Lane's avatar Tom Lane
Browse files

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
No related branches found
No related tags found
No related merge requests found
......@@ -14,7 +14,7 @@
*
*
* 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,
* 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,
......@@ -600,29 +597,26 @@ 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)
......@@ -639,14 +633,13 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid opid, Oid typid,
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");
......@@ -663,10 +656,9 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid opid, Oid typid,
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");
......@@ -683,10 +675,9 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid opid, Oid typid,
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");
......@@ -701,7 +692,6 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid opid, Oid typid,
}
}
heap_close(rel, AccessShareLock);
return true;
}
......
......@@ -7,7 +7,7 @@
*
*
* 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,
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));
......@@ -94,20 +93,13 @@ init_fcache(Oid foid,
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,
......@@ -115,27 +107,24 @@ init_fcache(Oid foid,
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.
......@@ -147,7 +136,7 @@ init_fcache(Oid foid,
retval->func_state = (char *) NULL;
retval->setArg = NULL;
retval->hasSetArg = false;
retval->oneResult = !procedureStruct->proretset;
retval->oneResult = ! procedureStruct->proretset;
retval->istrusted = procedureStruct->proistrusted;
/*
......@@ -157,8 +146,8 @@ init_fcache(Oid foid,
* 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;
......@@ -198,7 +187,7 @@ init_fcache(Oid foid,
{
Oid *argTypes;
retval->nullVect = (bool *) palloc((retval->nargs) * sizeof(bool));
retval->nullVect = (bool *) palloc(retval->nargs * sizeof(bool));
if (retval->language == SQLlanguageId)
{
......@@ -230,43 +219,36 @@ init_fcache(Oid foid,
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));
......@@ -275,7 +257,6 @@ init_fcache(Oid foid,
else
retval->func.fn_addr = (func_ptr) NULL;
return retval;
}
......
......@@ -6,7 +6,7 @@
* 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.
......@@ -617,35 +617,15 @@ get_typalign(Oid typid)
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);
......@@ -654,6 +634,22 @@ get_typdefault(Oid typid)
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;
......
......@@ -7,7 +7,7 @@
*
*
* 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
......@@ -535,140 +535,42 @@ SearchSysCacheTuple(int cacheId,/* cache selection code */
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);
}
......@@ -8,7 +8,7 @@
*
* 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,
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 */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment