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.
This commit is contained in:
parent
1161077e97
commit
27fee810ff
@ -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,
|
|||||||
* 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,
|
|||||||
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);
|
|
||||||
|
|
||||||
tuple = SearchSysCacheTuple(STATRELID,
|
|
||||||
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
|
/* We assume that there will only be one entry in pg_statistic
|
||||||
* for the given rel/att. Someday, VACUUM might store more than one...
|
* for the given rel/att. Someday, VACUUM might store more than one...
|
||||||
*/
|
*/
|
||||||
|
tuple = SearchSysCacheTuple(STATRELID,
|
||||||
|
ObjectIdGetDatum(relid),
|
||||||
|
Int16GetDatum((int16) attnum),
|
||||||
|
opid,
|
||||||
|
0);
|
||||||
|
if (!HeapTupleIsValid(tuple))
|
||||||
|
{
|
||||||
|
/* no such stats entry */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
heap_close(rel, AccessShareLock);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
85
src/backend/utils/cache/fcache.c
vendored
85
src/backend/utils/cache/fcache.c
vendored
@ -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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
* 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,
|
|||||||
{
|
{
|
||||||
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,
|
|||||||
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,
|
|||||||
else
|
else
|
||||||
retval->func.fn_addr = (func_ptr) NULL;
|
retval->func.fn_addr = (func_ptr) NULL;
|
||||||
|
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
44
src/backend/utils/cache/lsyscache.c
vendored
44
src/backend/utils/cache/lsyscache.c
vendored
@ -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)
|
|||||||
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)
|
|||||||
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;
|
||||||
|
|
||||||
|
158
src/backend/utils/cache/syscache.c
vendored
158
src/backend/utils/cache/syscache.c
vendored
@ -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 */
|
|||||||
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
|
|
||||||
* 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
|
* Given a tuple previously fetched by SearchSysCacheTuple() or
|
||||||
* fixed-location fields out of the struct returned by SearchSysCacheTuple.
|
* SearchSysCacheTupleCopy(), extract a specific attribute.
|
||||||
*
|
*
|
||||||
* [callers all assume this returns a (struct varlena *). -ay 10/94]
|
* 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/.
|
||||||
|
*
|
||||||
|
* 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]) ||
|
||||||
|
SysCache[cacheId]->relationId == InvalidOid ||
|
||||||
|
! PointerIsValid(SysCache[cacheId]->cc_tupdesc))
|
||||||
|
elog(ERROR, "SysCacheGetAttr: missing cache data for id %d", cacheId);
|
||||||
|
|
||||||
tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
|
return heap_getattr(tup, attributeNumber,
|
||||||
|
SysCache[cacheId]->cc_tupdesc,
|
||||||
if (!HeapTupleIsValid(tp))
|
isnull);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
@ -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,
|
|||||||
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 */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user