diff options
Diffstat (limited to 'src')
92 files changed, 2600 insertions, 2232 deletions
diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c index 6fe0e9652c2..ccf3071b502 100644 --- a/src/backend/access/common/printtup.c +++ b/src/backend/access/common/printtup.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.53 2000/05/30 04:24:27 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.54 2000/11/16 22:30:15 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -36,7 +36,7 @@ static void printtup_cleanup(DestReceiver *self); * getTypeOutAndElem -- get both typoutput and typelem for a type * * We used to fetch these with two separate function calls, - * typtoout() and gettypelem(), which each called SearchSysCacheTuple. + * typtoout() and gettypelem(), which each called SearchSysCache. * This way takes half the time. * ---------------- */ @@ -44,25 +44,19 @@ int getTypeOutAndElem(Oid type, Oid *typOutput, Oid *typElem) { HeapTuple typeTuple; - - typeTuple = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(type), - 0, 0, 0); - - if (HeapTupleIsValid(typeTuple)) - { - Form_pg_type pt = (Form_pg_type) GETSTRUCT(typeTuple); - - *typOutput = (Oid) pt->typoutput; - *typElem = (Oid) pt->typelem; - return OidIsValid(*typOutput); - } - - elog(ERROR, "getTypeOutAndElem: Cache lookup of type %u failed", type); - - *typOutput = InvalidOid; - *typElem = InvalidOid; - return 0; + Form_pg_type pt; + + typeTuple = SearchSysCache(TYPEOID, + ObjectIdGetDatum(type), + 0, 0, 0); + if (!HeapTupleIsValid(typeTuple)) + elog(ERROR, "getTypeOutAndElem: Cache lookup of type %u failed", type); + pt = (Form_pg_type) GETSTRUCT(typeTuple); + + *typOutput = pt->typoutput; + *typElem = pt->typelem; + ReleaseSysCache(typeTuple); + return OidIsValid(*typOutput); } /* ---------------- diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c index 1ed2366efda..8b9b7cd537f 100644 --- a/src/backend/access/common/tupdesc.c +++ b/src/backend/access/common/tupdesc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.68 2000/11/08 22:09:53 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.69 2000/11/16 22:30:15 tgl Exp $ * * NOTES * some of the executor utility code such as "ExecTypeFromTL" should be @@ -401,9 +401,9 @@ TupleDescInitEntry(TupleDesc desc, * -cim 6/14/90 * ---------------- */ - tuple = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(oidtypeid), - 0, 0, 0); + tuple = SearchSysCache(TYPEOID, + ObjectIdGetDatum(oidtypeid), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) { /* ---------------- @@ -455,25 +455,18 @@ TupleDescInitEntry(TupleDesc desc, */ if (attisset) { - Type t = typeidType(OIDOID); - - att->attlen = typeLen(t); - att->attbyval = typeByVal(t); + att->attlen = sizeof(Oid); + att->attbyval = true; + att->attstorage = 'p'; } else { att->attlen = typeForm->typlen; att->attbyval = typeForm->typbyval; -/* - * Default to the types storage - */ -#ifdef TUPLE_TOASTER_ACTIVE att->attstorage = typeForm->typstorage; -#else - att->attstorage = 'p'; -#endif } + ReleaseSysCache(tuple); return true; } @@ -496,12 +489,11 @@ TupleDescMakeSelfReference(TupleDesc desc, char *relname) { Form_pg_attribute att; - Type t = typeidType(OIDOID); att = desc->attrs[attnum - 1]; att->atttypid = TypeShellMake(relname); - att->attlen = typeLen(t); - att->attbyval = typeByVal(t); + att->attlen = sizeof(Oid); + att->attbyval = true; att->attstorage = 'p'; att->attnelems = 0; } @@ -580,7 +572,7 @@ BuildDescForRelation(List *schema, char *relname) } if (!TupleDescInitEntry(desc, attnum, attname, - typeTypeId(typenameType(typename)), + typenameTypeId(typename), atttypmod, attdim, attisset)) { /* ---------------- diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index d7bfeb1287d..d8e9005e933 100644 --- a/src/backend/access/gist/gist.c +++ b/src/backend/access/gist/gist.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.64 2000/11/08 22:09:53 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.65 2000/11/16 22:30:15 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1140,6 +1140,7 @@ initGISTstate(GISTSTATE *giststate, Relation index) equal_proc; HeapTuple htup; Form_pg_index itupform; + Oid indexrelid; consistent_proc = index_getprocid(index, 1, GIST_CONSISTENT_PROC); union_proc = index_getprocid(index, 1, GIST_UNION_PROC); @@ -1157,32 +1158,32 @@ initGISTstate(GISTSTATE *giststate, Relation index) fmgr_info(equal_proc, &giststate->equalFn); /* see if key type is different from type of attribute being indexed */ - htup = SearchSysCacheTuple(INDEXRELID, - ObjectIdGetDatum(RelationGetRelid(index)), - 0, 0, 0); - itupform = (Form_pg_index) GETSTRUCT(htup); + htup = SearchSysCache(INDEXRELID, + ObjectIdGetDatum(RelationGetRelid(index)), + 0, 0, 0); if (!HeapTupleIsValid(htup)) elog(ERROR, "initGISTstate: index %u not found", RelationGetRelid(index)); + itupform = (Form_pg_index) GETSTRUCT(htup); giststate->haskeytype = itupform->indhaskeytype; + indexrelid = itupform->indexrelid; + ReleaseSysCache(htup); + if (giststate->haskeytype) { /* key type is different -- is it byval? */ - htup = SearchSysCacheTuple(ATTNUM, - ObjectIdGetDatum(itupform->indexrelid), - UInt16GetDatum(FirstOffsetNumber), - 0, 0); + htup = SearchSysCache(ATTNUM, + ObjectIdGetDatum(indexrelid), + UInt16GetDatum(FirstOffsetNumber), + 0, 0); if (!HeapTupleIsValid(htup)) - { elog(ERROR, "initGISTstate: no attribute tuple %u %d", - itupform->indexrelid, FirstOffsetNumber); - return; - } + indexrelid, FirstOffsetNumber); giststate->keytypbyval = (((Form_pg_attribute) htup)->attbyval); + ReleaseSysCache(htup); } else giststate->keytypbyval = FALSE; - return; } diff --git a/src/backend/access/index/istrat.c b/src/backend/access/index/istrat.c index d6a966bcd44..681b80e1e86 100644 --- a/src/backend/access/index/istrat.c +++ b/src/backend/access/index/istrat.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.46 2000/07/14 22:17:30 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.47 2000/11/16 22:30:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -482,9 +482,9 @@ OperatorRelationFillScanKeyEntry(Relation operatorRelation, if (cachesearch) { - tuple = SearchSysCacheTuple(OPEROID, - ObjectIdGetDatum(operatorObjectId), - 0, 0, 0); + tuple = SearchSysCache(OPEROID, + ObjectIdGetDatum(operatorObjectId), + 0, 0, 0); } else { @@ -505,24 +505,25 @@ OperatorRelationFillScanKeyEntry(Relation operatorRelation, { if (!cachesearch) heap_endscan(scan); - elog(ERROR, "OperatorObjectIdFillScanKeyEntry: unknown operator %u", + elog(ERROR, "OperatorRelationFillScanKeyEntry: unknown operator %u", operatorObjectId); } entry->sk_flags = 0; entry->sk_procedure = ((Form_pg_operator) GETSTRUCT(tuple))->oprcode; - fmgr_info(entry->sk_procedure, &entry->sk_func); - entry->sk_nargs = entry->sk_func.fn_nargs; - if (!cachesearch) + if (cachesearch) + ReleaseSysCache(tuple); + else heap_endscan(scan); if (!RegProcedureIsValid(entry->sk_procedure)) - { elog(ERROR, - "OperatorObjectIdFillScanKeyEntry: no procedure for operator %u", + "OperatorRelationFillScanKeyEntry: no procedure for operator %u", operatorObjectId); - } + + fmgr_info(entry->sk_procedure, &entry->sk_func); + entry->sk_nargs = entry->sk_func.fn_nargs; } @@ -547,16 +548,16 @@ IndexSupportInitialize(IndexStrategy indexStrategy, HeapTuple tuple; Form_pg_index iform; StrategyMap map; - AttrNumber attributeNumber; - int attributeIndex; + AttrNumber attNumber; + int attIndex; Oid operatorClassObjectId[INDEX_MAX_KEYS]; bool cachesearch = (!IsBootstrapProcessingMode()) && IsCacheInitialized(); if (cachesearch) { - tuple = SearchSysCacheTuple(INDEXRELID, - ObjectIdGetDatum(indexObjectId), - 0, 0, 0); + tuple = SearchSysCache(INDEXRELID, + ObjectIdGetDatum(indexObjectId), + 0, 0, 0); } else { @@ -583,19 +584,23 @@ IndexSupportInitialize(IndexStrategy indexStrategy, * XXX note that the following assumes the INDEX tuple is well formed * and that the *key and *class are 0 terminated. */ - for (attributeIndex = 0; attributeIndex < maxAttributeNumber; attributeIndex++) + for (attIndex = 0; attIndex < maxAttributeNumber; attIndex++) { - if (!OidIsValid(iform->indkey[attributeIndex])) + if (!OidIsValid(iform->indkey[attIndex])) { - if (attributeIndex == InvalidAttrNumber) + if (attIndex == InvalidAttrNumber) elog(ERROR, "IndexSupportInitialize: no pg_index tuple"); break; } - operatorClassObjectId[attributeIndex] = iform->indclass[attributeIndex]; + operatorClassObjectId[attIndex] = iform->indclass[attIndex]; } - if (!cachesearch) + if (cachesearch) + { + ReleaseSysCache(tuple); + } + else { heap_endscan(scan); heap_close(relation, AccessShareLock); @@ -614,20 +619,19 @@ IndexSupportInitialize(IndexStrategy indexStrategy, relation = heap_openr(AccessMethodProcedureRelationName, AccessShareLock); - for (attributeNumber = 1; attributeNumber <= maxAttributeNumber; - attributeNumber++) + for (attNumber = 1; attNumber <= maxAttributeNumber; attNumber++) { int16 support; Form_pg_amproc aform; RegProcedure *loc; - loc = &indexSupport[((attributeNumber - 1) * maxSupportNumber)]; + loc = &indexSupport[((attNumber - 1) * maxSupportNumber)]; for (support = 0; support < maxSupportNumber; ++support) loc[support] = InvalidOid; entry[1].sk_argument = - ObjectIdGetDatum(operatorClassObjectId[attributeNumber - 1]); + ObjectIdGetDatum(operatorClassObjectId[attNumber - 1]); scan = heap_beginscan(relation, false, SnapshotNow, 2, entry); @@ -654,17 +658,16 @@ IndexSupportInitialize(IndexStrategy indexStrategy, relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock); operatorRelation = heap_openr(OperatorRelationName, AccessShareLock); - for (attributeNumber = maxAttributeNumber; attributeNumber > 0; - attributeNumber--) + for (attNumber = maxAttributeNumber; attNumber > 0; attNumber--) { StrategyNumber strategy; entry[1].sk_argument = - ObjectIdGetDatum(operatorClassObjectId[attributeNumber - 1]); + ObjectIdGetDatum(operatorClassObjectId[attNumber - 1]); map = IndexStrategyGetStrategyMap(indexStrategy, maxStrategyNumber, - attributeNumber); + attNumber); for (strategy = 1; strategy <= maxStrategyNumber; strategy++) ScanKeyEntrySetIllegal(StrategyMapGetScanKeyEntry(map, strategy)); diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 6d950e96942..600e9ddcaec 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.82 2000/11/10 00:33:08 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.83 2000/11/16 22:30:16 tgl Exp $ * * NOTES * Transaction aborts can now occur two ways: @@ -1112,6 +1112,7 @@ CommitTransaction(void) AtEOXact_nbtree(); AtCommit_Cache(); AtCommit_Locks(); + AtEOXact_CatCache(true); AtCommit_Memory(); AtEOXact_Files(); @@ -1192,6 +1193,7 @@ AbortTransaction(void) AtEOXact_SPI(); AtEOXact_nbtree(); AtAbort_Cache(); + AtEOXact_CatCache(false); AtAbort_Memory(); AtEOXact_Files(); diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index b7013d28824..b2698ad19b6 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.42 2000/11/03 19:02:18 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.43 2000/11/16 22:30:17 tgl Exp $ * * NOTES * See acl.h. @@ -77,6 +77,7 @@ ChangeAcl(char *relname, *new_acl; Relation relation; HeapTuple tuple; + HeapTuple newtuple; Datum aclDatum; Datum values[Natts_pg_class]; char nulls[Natts_pg_class]; @@ -89,9 +90,9 @@ ChangeAcl(char *relname, * there's no ACL, create a default using the pg_class.relowner field. */ relation = heap_openr(RelationRelationName, RowExclusiveLock); - tuple = SearchSysCacheTuple(RELNAME, - PointerGetDatum(relname), - 0, 0, 0); + tuple = SearchSysCache(RELNAME, + PointerGetDatum(relname), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) { heap_close(relation, RowExclusiveLock); @@ -134,14 +135,16 @@ ChangeAcl(char *relname, } replaces[Anum_pg_class_relacl - 1] = 'r'; values[Anum_pg_class_relacl - 1] = PointerGetDatum(new_acl); - tuple = heap_modifytuple(tuple, relation, values, nulls, replaces); + newtuple = heap_modifytuple(tuple, relation, values, nulls, replaces); - heap_update(relation, &tuple->t_self, tuple, NULL); + ReleaseSysCache(tuple); + + heap_update(relation, &newtuple->t_self, newtuple, NULL); /* keep the catalog indices up to date */ CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs); - CatalogIndexInsert(idescs, Num_pg_class_indices, relation, tuple); + CatalogIndexInsert(idescs, Num_pg_class_indices, relation, newtuple); CatalogCloseIndices(Num_pg_class_indices, idescs); heap_close(relation, RowExclusiveLock); @@ -156,11 +159,14 @@ get_grosysid(char *groname) HeapTuple tuple; AclId id = 0; - tuple = SearchSysCacheTuple(GRONAME, - PointerGetDatum(groname), - 0, 0, 0); + tuple = SearchSysCache(GRONAME, + PointerGetDatum(groname), + 0, 0, 0); if (HeapTupleIsValid(tuple)) + { id = ((Form_pg_group) GETSTRUCT(tuple))->grosysid; + ReleaseSysCache(tuple); + } else elog(ERROR, "non-existent group \"%s\"", groname); return id; @@ -172,11 +178,14 @@ get_groname(AclId grosysid) HeapTuple tuple; char *name = NULL; - tuple = SearchSysCacheTuple(GROSYSID, - ObjectIdGetDatum(grosysid), - 0, 0, 0); + tuple = SearchSysCache(GROSYSID, + ObjectIdGetDatum(grosysid), + 0, 0, 0); if (HeapTupleIsValid(tuple)) - name = NameStr(((Form_pg_group) GETSTRUCT(tuple))->groname); + { + name = pstrdup(NameStr(((Form_pg_group) GETSTRUCT(tuple))->groname)); + ReleaseSysCache(tuple); + } else elog(NOTICE, "get_groname: group %u not found", grosysid); return name; @@ -185,6 +194,7 @@ get_groname(AclId grosysid) static bool in_group(AclId uid, AclId gid) { + bool result = false; HeapTuple tuple; Datum att; bool isNull; @@ -193,9 +203,9 @@ in_group(AclId uid, AclId gid) int i, num; - tuple = SearchSysCacheTuple(GROSYSID, - ObjectIdGetDatum(gid), - 0, 0, 0); + tuple = SearchSysCache(GROSYSID, + ObjectIdGetDatum(gid), + 0, 0, 0); if (HeapTupleIsValid(tuple)) { att = SysCacheGetAttr(GROSYSID, @@ -212,13 +222,17 @@ in_group(AclId uid, AclId gid) for (i = 0; i < num; ++i) { if (aidp[i] == uid) - return true; + { + result = true; + break; + } } } + ReleaseSysCache(tuple); } else elog(NOTICE, "in_group: group %u not found", gid); - return false; + return result; } /* @@ -342,9 +356,9 @@ pg_aclcheck(char *relname, Oid userid, AclMode mode) bool isNull; Acl *acl; - tuple = SearchSysCacheTuple(SHADOWSYSID, - ObjectIdGetDatum(userid), - 0, 0, 0); + tuple = SearchSysCache(SHADOWSYSID, + ObjectIdGetDatum(userid), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "pg_aclcheck: invalid user id %u", (unsigned) userid); @@ -363,6 +377,7 @@ pg_aclcheck(char *relname, Oid userid, AclMode mode) { elog(DEBUG, "pg_aclcheck: catalog update to \"%s\": permission denied", relname); + ReleaseSysCache(tuple); return ACLCHECK_NO_PRIV; } @@ -375,15 +390,19 @@ pg_aclcheck(char *relname, Oid userid, AclMode mode) elog(DEBUG, "pg_aclcheck: \"%s\" is superuser", usename); #endif + ReleaseSysCache(tuple); return ACLCHECK_OK; } + ReleaseSysCache(tuple); + /* caution: usename is inaccessible beyond this point... */ + /* * Normal case: get the relation's ACL from pg_class */ - tuple = SearchSysCacheTuple(RELNAME, - PointerGetDatum(relname), - 0, 0, 0); + tuple = SearchSysCache(RELNAME, + PointerGetDatum(relname), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "pg_aclcheck: class \"%s\" not found", relname); @@ -404,8 +423,11 @@ pg_aclcheck(char *relname, Oid userid, AclMode mode) } result = aclcheck(relname, acl, userid, (AclIdType) ACL_IDTYPE_UID, mode); + if (acl) pfree(acl); + ReleaseSysCache(tuple); + return result; } @@ -415,12 +437,12 @@ pg_ownercheck(Oid userid, int cacheid) { HeapTuple tuple; - AclId owner_id = 0; + AclId owner_id; char *usename; - tuple = SearchSysCacheTuple(SHADOWSYSID, - ObjectIdGetDatum(userid), - 0, 0, 0); + tuple = SearchSysCache(SHADOWSYSID, + ObjectIdGetDatum(userid), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "pg_ownercheck: invalid user id %u", (unsigned) userid); @@ -435,11 +457,16 @@ pg_ownercheck(Oid userid, elog(DEBUG, "pg_ownercheck: user \"%s\" is superuser", usename); #endif + ReleaseSysCache(tuple); return 1; } - tuple = SearchSysCacheTuple(cacheid, PointerGetDatum(value), - 0, 0, 0); + ReleaseSysCache(tuple); + /* caution: usename is inaccessible beyond this point... */ + + tuple = SearchSysCache(cacheid, + PointerGetDatum(value), + 0, 0, 0); switch (cacheid) { case OPEROID: @@ -468,9 +495,12 @@ pg_ownercheck(Oid userid, break; default: elog(ERROR, "pg_ownercheck: invalid cache id: %d", cacheid); + owner_id = 0; /* keep compiler quiet */ break; } + ReleaseSysCache(tuple); + return userid == owner_id; } @@ -482,15 +512,15 @@ pg_func_ownercheck(Oid userid, { HeapTuple tuple; AclId owner_id; - char *username; + char *usename; - tuple = SearchSysCacheTuple(SHADOWSYSID, - ObjectIdGetDatum(userid), - 0, 0, 0); + tuple = SearchSysCache(SHADOWSYSID, + ObjectIdGetDatum(userid), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "pg_func_ownercheck: invalid user id %u", (unsigned) userid); - username = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename); + usename = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename); /* * Superusers bypass all permission-checking. @@ -499,21 +529,27 @@ pg_func_ownercheck(Oid userid, { #ifdef ACLDEBUG_TRACE elog(DEBUG, "pg_ownercheck: user \"%s\" is superuser", - username); + usename); #endif + ReleaseSysCache(tuple); return 1; } - tuple = SearchSysCacheTuple(PROCNAME, - PointerGetDatum(funcname), - Int32GetDatum(nargs), - PointerGetDatum(arglist), - 0); + ReleaseSysCache(tuple); + /* caution: usename is inaccessible beyond this point... */ + + tuple = SearchSysCache(PROCNAME, + PointerGetDatum(funcname), + Int32GetDatum(nargs), + PointerGetDatum(arglist), + 0); if (!HeapTupleIsValid(tuple)) func_error("pg_func_ownercheck", funcname, nargs, arglist, NULL); owner_id = ((Form_pg_proc) GETSTRUCT(tuple))->proowner; + ReleaseSysCache(tuple); + return userid == owner_id; } @@ -524,15 +560,15 @@ pg_aggr_ownercheck(Oid userid, { HeapTuple tuple; AclId owner_id; - char *username; + char *usename; - tuple = SearchSysCacheTuple(SHADOWSYSID, - PointerGetDatum(userid), - 0, 0, 0); + tuple = SearchSysCache(SHADOWSYSID, + PointerGetDatum(userid), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "pg_aggr_ownercheck: invalid user id %u", (unsigned) userid); - username = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename); + usename = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename); /* * Superusers bypass all permission-checking. @@ -541,20 +577,25 @@ pg_aggr_ownercheck(Oid userid, { #ifdef ACLDEBUG_TRACE elog(DEBUG, "pg_aggr_ownercheck: user \"%s\" is superuser", - username); + usename); #endif + ReleaseSysCache(tuple); return 1; } - tuple = SearchSysCacheTuple(AGGNAME, - PointerGetDatum(aggname), - ObjectIdGetDatum(basetypeID), - 0, 0); + ReleaseSysCache(tuple); + /* caution: usename is inaccessible beyond this point... */ + tuple = SearchSysCache(AGGNAME, + PointerGetDatum(aggname), + ObjectIdGetDatum(basetypeID), + 0, 0); if (!HeapTupleIsValid(tuple)) agg_error("pg_aggr_ownercheck", aggname, basetypeID); owner_id = ((Form_pg_aggregate) GETSTRUCT(tuple))->aggowner; + ReleaseSysCache(tuple); + return userid == owner_id; } diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c index c7b191dd2da..aed3864e900 100644 --- a/src/backend/catalog/catalog.c +++ b/src/backend/catalog/catalog.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.36 2000/10/22 05:14:01 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.37 2000/11/16 22:30:17 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -20,7 +20,7 @@ #include "catalog/catname.h" #include "catalog/pg_type.h" #include "miscadmin.h" -#include "utils/syscache.h" +#include "utils/lsyscache.h" #ifdef OLD_FILE_NAMING /* @@ -251,12 +251,10 @@ newoid() void fillatt(TupleDesc tupleDesc) { - Form_pg_attribute *attributeP; - Form_pg_type typp; - HeapTuple tuple; - int i; int natts = tupleDesc->natts; Form_pg_attribute *att = tupleDesc->attrs; + Form_pg_attribute *attributeP; + int i; if (natts < 0 || natts > MaxHeapAttributeNumber) elog(ERROR, "fillatt: %d attributes is too large", natts); @@ -268,33 +266,23 @@ fillatt(TupleDesc tupleDesc) attributeP = &att[0]; - for (i = 0; i < natts;) + for (i = 1; i <= natts; i++) { - tuple = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum((*attributeP)->atttypid), - 0, 0, 0); - if (!HeapTupleIsValid(tuple)) + (*attributeP)->attnum = (int16) i; + + /* + * Check if the attr is a set before messing with the length + * and byval, since those were already set in + * TupleDescInitEntry. In fact, this seems redundant here, + * but who knows what I'll break if I take it out... + */ + if (!(*attributeP)->attisset) { - elog(ERROR, "fillatt: unknown atttypid %d", - (*attributeP)->atttypid); + get_typlenbyval((*attributeP)->atttypid, + & (*attributeP)->attlen, + & (*attributeP)->attbyval); } - else - { - (*attributeP)->attnum = (int16) ++i; - /* - * Check if the attr is a set before messing with the length - * and byval, since those were already set in - * TupleDescInitEntry. In fact, this seems redundant here, - * but who knows what I'll break if I take it out... - */ - if (!(*attributeP)->attisset) - { - typp = (Form_pg_type) GETSTRUCT(tuple); /* XXX */ - (*attributeP)->attlen = typp->typlen; - (*attributeP)->attbyval = typp->typbyval; - } - } - attributeP += 1; + attributeP++; } } diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 2c4a9e515b2..3da6d82d4d0 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.151 2000/11/08 22:09:56 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.152 2000/11/16 22:30:17 tgl Exp $ * * * INTERFACE ROUTINES @@ -488,7 +488,6 @@ CheckAttributeNames(TupleDesc tupdesc) Oid RelnameFindRelid(const char *relname) { - HeapTuple tuple; Oid relid; /* @@ -497,19 +496,16 @@ RelnameFindRelid(const char *relname) */ if (!IsBootstrapProcessingMode()) { - tuple = SearchSysCacheTuple(RELNAME, - PointerGetDatum(relname), - 0, 0, 0); - if (HeapTupleIsValid(tuple)) - relid = tuple->t_data->t_oid; - else - relid = InvalidOid; + relid = GetSysCacheOid(RELNAME, + PointerGetDatum(relname), + 0, 0, 0); } else { Relation pg_class_desc; ScanKeyData key; HeapScanDesc pg_class_scan; + HeapTuple tuple; pg_class_desc = heap_openr(RelationRelationName, AccessShareLock); @@ -756,8 +752,8 @@ AddNewRelationType(char *typeName, Oid new_rel_oid) */ new_type_oid = TypeCreate(typeName, /* type name */ new_rel_oid, /* relation oid */ - typeLen(typeidType(OIDOID)), /* internal size */ - typeLen(typeidType(OIDOID)), /* external size */ + sizeof(Oid), /* internal size */ + sizeof(Oid), /* external size */ 'c', /* type-type (catalog) */ ',', /* default array delimiter */ "int4in", /* input procedure */ @@ -1080,15 +1076,12 @@ DeleteRelationTuple(Relation rel) */ pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock); - tup = SearchSysCacheTupleCopy(RELOID, - ObjectIdGetDatum(rel->rd_id), - 0, 0, 0); + tup = SearchSysCacheCopy(RELOID, + ObjectIdGetDatum(rel->rd_id), + 0, 0, 0); if (!HeapTupleIsValid(tup)) - { - heap_close(pg_class_desc, RowExclusiveLock); elog(ERROR, "Relation \"%s\" does not exist", RelationGetRelationName(rel)); - } /* ---------------- * delete the relation tuple from pg_class, and finish up. @@ -1136,14 +1129,15 @@ RelationTruncateIndexes(Oid heapId) indexId = ((Form_pg_index) GETSTRUCT(indexTuple))->indexrelid; indexInfo = BuildIndexInfo(indexTuple); - /* Fetch the pg_class tuple associated with this index */ - classTuple = SearchSysCacheTupleCopy(RELOID, - ObjectIdGetDatum(indexId), - 0, 0, 0); + /* Fetch access method from pg_class tuple for this index */ + classTuple = SearchSysCache(RELOID, + ObjectIdGetDatum(indexId), + 0, 0, 0); if (!HeapTupleIsValid(classTuple)) elog(ERROR, "RelationTruncateIndexes: index %u not found in pg_class", indexId); accessMethodId = ((Form_pg_class) GETSTRUCT(classTuple))->relam; + ReleaseSysCache(classTuple); /* * We have to re-open the heap rel each time through this loop @@ -1258,19 +1252,17 @@ DeleteAttributeTuples(Relation rel) attnum <= rel->rd_att->natts; attnum++) { - if (HeapTupleIsValid(tup = SearchSysCacheTupleCopy(ATTNUM, + tup = SearchSysCacheCopy(ATTNUM, ObjectIdGetDatum(RelationGetRelid(rel)), - Int16GetDatum(attnum), - 0, 0))) + Int16GetDatum(attnum), + 0, 0); + if (HeapTupleIsValid(tup)) { - /*** Delete any comments associated with this attribute ***/ - DeleteComments(tup->t_data->t_oid); heap_delete(pg_attribute_desc, &tup->t_self, NULL); heap_freetuple(tup); - } } @@ -1586,9 +1578,10 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin, return; /* done if pg_attribute is OK */ attrrel = heap_openr(AttributeRelationName, RowExclusiveLock); - atttup = SearchSysCacheTupleCopy(ATTNUM, - ObjectIdGetDatum(RelationGetRelid(rel)), - (Datum) attnum, 0, 0); + atttup = SearchSysCacheCopy(ATTNUM, + ObjectIdGetDatum(RelationGetRelid(rel)), + Int16GetDatum(attnum), + 0, 0); if (!HeapTupleIsValid(atttup)) elog(ERROR, "cache lookup of attribute %d in relation %u failed", attnum, RelationGetRelid(rel)); @@ -1953,11 +1946,12 @@ AddRelationRawConstraints(Relation rel, * message, but for ALTER TABLE ADD ATTRIBUTE this'd be important.) */ relrel = heap_openr(RelationRelationName, RowExclusiveLock); - reltup = SearchSysCacheTupleCopy(RELOID, - ObjectIdGetDatum(RelationGetRelid(rel)), - 0, 0, 0); + reltup = SearchSysCacheCopy(RELOID, + ObjectIdGetDatum(RelationGetRelid(rel)), + 0, 0, 0); if (!HeapTupleIsValid(reltup)) - elog(ERROR, "cache lookup of relation %u failed", RelationGetRelid(rel)); + elog(ERROR, "cache lookup of relation %u failed", + RelationGetRelid(rel)); relStruct = (Form_pg_class) GETSTRUCT(reltup); relStruct->relchecks = numchecks; @@ -1970,8 +1964,8 @@ AddRelationRawConstraints(Relation rel, CatalogIndexInsert(relidescs, Num_pg_class_indices, relrel, reltup); CatalogCloseIndices(Num_pg_class_indices, relidescs); - heap_close(relrel, RowExclusiveLock); heap_freetuple(reltup); + heap_close(relrel, RowExclusiveLock); } static void diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 3833c961f40..d379246a922 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.129 2000/11/08 22:09:56 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.130 2000/11/16 22:30:17 tgl Exp $ * * * INTERFACE ROUTINES @@ -174,9 +174,9 @@ BuildFuncTupleDesc(Oid funcOid) /* * Lookup the function to get its name and return type. */ - tuple = SearchSysCacheTuple(PROCOID, - ObjectIdGetDatum(funcOid), - 0, 0, 0); + tuple = SearchSysCache(PROCOID, + ObjectIdGetDatum(funcOid), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "Function %u does not exist", funcOid); retType = ((Form_pg_proc) GETSTRUCT(tuple))->prorettype; @@ -187,12 +187,14 @@ BuildFuncTupleDesc(Oid funcOid) namestrcpy(&funcTupDesc->attrs[0]->attname, NameStr(((Form_pg_proc) GETSTRUCT(tuple))->proname)); + ReleaseSysCache(tuple); + /* * Lookup the return type in pg_type for the type length etc. */ - tuple = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(retType), - 0, 0, 0); + tuple = SearchSysCache(TYPEOID, + ObjectIdGetDatum(retType), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "Type %u does not exist", retType); @@ -208,6 +210,8 @@ BuildFuncTupleDesc(Oid funcOid) funcTupDesc->attrs[0]->attstorage = 'p'; funcTupDesc->attrs[0]->attalign = ((Form_pg_type) GETSTRUCT(tuple))->typalign; + ReleaseSysCache(tuple); + return funcTupDesc; } @@ -759,10 +763,12 @@ UpdateIndexPredicate(Oid indexoid, Node *oldPred, Node *predicate) /* open the index system catalog relation */ pg_index = heap_openr(IndexRelationName, RowExclusiveLock); - tuple = SearchSysCacheTuple(INDEXRELID, - ObjectIdGetDatum(indexoid), - 0, 0, 0); - Assert(HeapTupleIsValid(tuple)); + tuple = SearchSysCache(INDEXRELID, + ObjectIdGetDatum(indexoid), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "UpdateIndexPredicate: cache lookup failed for index %u", + indexoid); for (i = 0; i < Natts_pg_index; i++) { @@ -779,6 +785,8 @@ UpdateIndexPredicate(Oid indexoid, Node *oldPred, Node *predicate) heap_update(pg_index, &newtup->t_self, newtup, NULL); heap_freetuple(newtup); + ReleaseSysCache(tuple); + heap_close(pg_index, RowExclusiveLock); pfree(predText); } @@ -1069,11 +1077,12 @@ index_drop(Oid indexId) relationRelation = heap_openr(RelationRelationName, RowExclusiveLock); /* Remove the pg_class tuple for the index itself */ - tuple = SearchSysCacheTupleCopy(RELOID, - ObjectIdGetDatum(indexId), - 0, 0, 0); - - Assert(HeapTupleIsValid(tuple)); + tuple = SearchSysCacheCopy(RELOID, + ObjectIdGetDatum(indexId), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "index_drop: cache lookup failed for index %u", + indexId); heap_delete(relationRelation, &tuple->t_self, NULL); heap_freetuple(tuple); @@ -1098,10 +1107,10 @@ index_drop(Oid indexId) attnum = 1; /* indexes start at 1 */ - while (HeapTupleIsValid(tuple = SearchSysCacheTupleCopy(ATTNUM, + while (HeapTupleIsValid(tuple = SearchSysCacheCopy(ATTNUM, ObjectIdGetDatum(indexId), Int16GetDatum(attnum), - 0, 0))) + 0, 0))) { heap_delete(attributeRelation, &tuple->t_self, NULL); heap_freetuple(tuple); @@ -1115,10 +1124,12 @@ index_drop(Oid indexId) */ indexRelation = heap_openr(IndexRelationName, RowExclusiveLock); - tuple = SearchSysCacheTupleCopy(INDEXRELID, - ObjectIdGetDatum(indexId), - 0, 0, 0); - Assert(HeapTupleIsValid(tuple)); + tuple = SearchSysCacheCopy(INDEXRELID, + ObjectIdGetDatum(indexId), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "index_drop: cache lookup failed for index %u", + indexId); heap_delete(indexRelation, &tuple->t_self, NULL); heap_freetuple(tuple); @@ -1318,21 +1329,24 @@ LockClassinfoForUpdate(Oid relid, HeapTuple rtup, Buffer *buffer, bool confirmCommitted) { HeapTuple classTuple; - Form_pg_class pgcform; bool test; Relation relationRelation; - classTuple = SearchSysCacheTuple(RELOID, PointerGetDatum(relid), - 0, 0, 0); - if (!HeapTupleIsValid(classTuple)) - return false; - rtup->t_self = classTuple->t_self; - pgcform = (Form_pg_class) GETSTRUCT(classTuple); /* * NOTE: get and hold RowExclusiveLock on pg_class, because caller will * probably modify the rel's pg_class tuple later on. */ relationRelation = heap_openr(RelationRelationName, RowExclusiveLock); + classTuple = SearchSysCache(RELOID, PointerGetDatum(relid), + 0, 0, 0); + if (!HeapTupleIsValid(classTuple)) + { + heap_close(relationRelation, NoLock); + return false; + } + rtup->t_self = classTuple->t_self; + ReleaseSysCache(classTuple); + test = heap_mark4update(relationRelation, rtup, buffer); switch (test) { @@ -1418,9 +1432,9 @@ setRelhasindex(Oid relid, bool hasindex) if (!IsIgnoringSystemIndexes()) { - tuple = SearchSysCacheTupleCopy(RELOID, - ObjectIdGetDatum(relid), - 0, 0, 0); + tuple = SearchSysCacheCopy(RELOID, + ObjectIdGetDatum(relid), + 0, 0, 0); } else { @@ -1542,9 +1556,9 @@ UpdateStats(Oid relid, long reltuples) if (!in_place_upd) { - tuple = SearchSysCacheTupleCopy(RELOID, - ObjectIdGetDatum(relid), - 0, 0, 0); + tuple = SearchSysCacheCopy(RELOID, + ObjectIdGetDatum(relid), + 0, 0, 0); } else { @@ -1887,19 +1901,20 @@ IndexGetRelation(Oid indexId) { HeapTuple tuple; Form_pg_index index; + Oid result; - tuple = SearchSysCacheTuple(INDEXRELID, - ObjectIdGetDatum(indexId), - 0, 0, 0); + tuple = SearchSysCache(INDEXRELID, + ObjectIdGetDatum(indexId), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) - { elog(ERROR, "IndexGetRelation: can't find index id %u", indexId); - } index = (Form_pg_index) GETSTRUCT(tuple); Assert(index->indexrelid == indexId); - return index->indrelid; + result = index->indrelid; + ReleaseSysCache(tuple); + return result; } /* --------------------------------- @@ -1965,12 +1980,13 @@ reindex_index(Oid indexId, bool force) heap_close(indexRelation, AccessShareLock); /* Fetch the classTuple associated with this index */ - classTuple = SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(indexId), - 0, 0, 0); + classTuple = SearchSysCache(RELOID, + ObjectIdGetDatum(indexId), + 0, 0, 0); if (!HeapTupleIsValid(classTuple)) elog(ERROR, "reindex_index: index %u not found in pg_class", indexId); accessMethodId = ((Form_pg_class) GETSTRUCT(classTuple))->relam; + ReleaseSysCache(classTuple); /* Open our index relation */ heapRelation = heap_open(heapId, ExclusiveLock); diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c index 6003ab6bc53..60eae115ec7 100644 --- a/src/backend/catalog/indexing.c +++ b/src/backend/catalog/indexing.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.73 2000/11/10 00:33:09 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.74 2000/11/16 22:30:17 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -153,13 +153,14 @@ CatalogIndexInsert(Relation *idescs, IndexInfo *indexInfo; InsertIndexResult indexRes; - index_tup = SearchSysCacheTuple(INDEXRELID, - ObjectIdGetDatum(idescs[i]->rd_id), - 0, 0, 0); + index_tup = SearchSysCache(INDEXRELID, + ObjectIdGetDatum(idescs[i]->rd_id), + 0, 0, 0); if (!HeapTupleIsValid(index_tup)) elog(ERROR, "CatalogIndexInsert: index %u not found", idescs[i]->rd_id); indexInfo = BuildIndexInfo(index_tup); + ReleaseSysCache(index_tup); FormIndexDatum(indexInfo, heapTuple, diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c index e3fa7c5535b..9c9d54c8f3e 100644 --- a/src/backend/catalog/pg_aggregate.c +++ b/src/backend/catalog/pg_aggregate.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.35 2000/07/17 03:04:43 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.36 2000/11/16 22:30:17 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -82,15 +82,10 @@ AggregateCreate(char *aggName, * specified as 'ANY' for a data-independent transition function, * such as COUNT(*). */ - tup = SearchSysCacheTuple(TYPENAME, + basetype = GetSysCacheOid(TYPENAME, PointerGetDatum(aggbasetypeName), 0, 0, 0); - if (HeapTupleIsValid(tup)) - { - basetype = tup->t_data->t_oid; - Assert(OidIsValid(basetype)); - } - else + if (!OidIsValid(basetype)) { if (strcasecmp(aggbasetypeName, "ANY") != 0) elog(ERROR, "AggregateCreate: Type '%s' undefined", @@ -99,24 +94,21 @@ AggregateCreate(char *aggName, } /* make sure there is no existing agg of same name and base type */ - tup = SearchSysCacheTuple(AGGNAME, - PointerGetDatum(aggName), - ObjectIdGetDatum(basetype), - 0, 0); - if (HeapTupleIsValid(tup)) + if (SearchSysCacheExists(AGGNAME, + PointerGetDatum(aggName), + ObjectIdGetDatum(basetype), + 0, 0)) elog(ERROR, "AggregateCreate: aggregate '%s' with base type '%s' already exists", aggName, aggbasetypeName); /* handle transtype */ - tup = SearchSysCacheTuple(TYPENAME, - PointerGetDatum(aggtranstypeName), - 0, 0, 0); - if (!HeapTupleIsValid(tup)) + transtype = GetSysCacheOid(TYPENAME, + PointerGetDatum(aggtranstypeName), + 0, 0, 0); + if (!OidIsValid(transtype)) elog(ERROR, "AggregateCreate: Type '%s' undefined", aggtranstypeName); - transtype = tup->t_data->t_oid; - Assert(OidIsValid(transtype)); /* handle transfn */ fnArgs[0] = transtype; @@ -129,48 +121,50 @@ AggregateCreate(char *aggName, { nargs = 1; } - tup = SearchSysCacheTuple(PROCNAME, - PointerGetDatum(aggtransfnName), - Int32GetDatum(nargs), - PointerGetDatum(fnArgs), - 0); + tup = SearchSysCache(PROCNAME, + PointerGetDatum(aggtransfnName), + Int32GetDatum(nargs), + PointerGetDatum(fnArgs), + 0); if (!HeapTupleIsValid(tup)) func_error("AggregateCreate", aggtransfnName, nargs, fnArgs, NULL); transfn = tup->t_data->t_oid; + Assert(OidIsValid(transfn)); proc = (Form_pg_proc) GETSTRUCT(tup); if (proc->prorettype != transtype) elog(ERROR, "AggregateCreate: return type of '%s' is not '%s'", aggtransfnName, aggtranstypeName); - Assert(OidIsValid(transfn)); /* * If the transfn is strict and the initval is NULL, make sure * input type and transtype are the same (or at least binary- * compatible), so that it's OK to use the first input value * as the initial transValue. */ - if (((Form_pg_proc) GETSTRUCT(tup))->proisstrict && agginitval == NULL) + if (proc->proisstrict && agginitval == NULL) { if (basetype != transtype && ! IS_BINARY_COMPATIBLE(basetype, transtype)) elog(ERROR, "AggregateCreate: must not omit initval when transfn is strict and transtype is not compatible with input type"); } + ReleaseSysCache(tup); /* handle finalfn, if supplied */ if (aggfinalfnName) { fnArgs[0] = transtype; fnArgs[1] = 0; - tup = SearchSysCacheTuple(PROCNAME, - PointerGetDatum(aggfinalfnName), - Int32GetDatum(1), - PointerGetDatum(fnArgs), - 0); + tup = SearchSysCache(PROCNAME, + PointerGetDatum(aggfinalfnName), + Int32GetDatum(1), + PointerGetDatum(fnArgs), + 0); if (!HeapTupleIsValid(tup)) func_error("AggregateCreate", aggfinalfnName, 1, fnArgs, NULL); finalfn = tup->t_data->t_oid; + Assert(OidIsValid(finalfn)); proc = (Form_pg_proc) GETSTRUCT(tup); finaltype = proc->prorettype; - Assert(OidIsValid(finalfn)); + ReleaseSysCache(tup); } else { @@ -237,10 +231,10 @@ AggNameGetInitVal(char *aggName, Oid basetype, bool *isNull) Assert(PointerIsValid(aggName)); Assert(PointerIsValid(isNull)); - tup = SearchSysCacheTuple(AGGNAME, - PointerGetDatum(aggName), - ObjectIdGetDatum(basetype), - 0, 0); + tup = SearchSysCache(AGGNAME, + PointerGetDatum(aggName), + ObjectIdGetDatum(basetype), + 0, 0); if (!HeapTupleIsValid(tup)) elog(ERROR, "AggNameGetInitVal: cache lookup failed for aggregate '%s'", aggName); @@ -254,20 +248,24 @@ AggNameGetInitVal(char *aggName, Oid basetype, bool *isNull) Anum_pg_aggregate_agginitval, isNull); if (*isNull) + { + ReleaseSysCache(tup); return (Datum) 0; + } strInitVal = DatumGetCString(DirectFunctionCall1(textout, textInitVal)); - tup = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(transtype), - 0, 0, 0); + ReleaseSysCache(tup); + + tup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(transtype), + 0, 0, 0); if (!HeapTupleIsValid(tup)) - { - pfree(strInitVal); elog(ERROR, "AggNameGetInitVal: cache lookup failed on aggregate transition function return type %u", transtype); - } + typinput = ((Form_pg_type) GETSTRUCT(tup))->typinput; typelem = ((Form_pg_type) GETSTRUCT(tup))->typelem; + ReleaseSysCache(tup); initVal = OidFunctionCall3(typinput, CStringGetDatum(strInitVal), diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c index 388bad8a583..29f404063ff 100644 --- a/src/backend/catalog/pg_operator.c +++ b/src/backend/catalog/pg_operator.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.52 2000/10/22 23:32:38 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.53 2000/11/16 22:30:17 tgl Exp $ * * NOTES * these routines moved here from commands/define.c and somewhat cleaned up. @@ -575,12 +575,11 @@ OperatorDef(char *operatorName, typeId[1] = rightTypeId; nargs = 2; } - tup = SearchSysCacheTuple(PROCNAME, - PointerGetDatum(procedureName), - Int32GetDatum(nargs), - PointerGetDatum(typeId), - 0); - + tup = SearchSysCache(PROCNAME, + PointerGetDatum(procedureName), + Int32GetDatum(nargs), + PointerGetDatum(typeId), + 0); if (!HeapTupleIsValid(tup)) func_error("OperatorDef", procedureName, nargs, typeId, NULL); @@ -588,27 +587,32 @@ OperatorDef(char *operatorName, values[Anum_pg_operator_oprresult - 1] = ObjectIdGetDatum(((Form_pg_proc) GETSTRUCT(tup))->prorettype); + ReleaseSysCache(tup); + /* ---------------- * find restriction * ---------------- */ if (restrictionName) { /* optional */ + Oid restOid; + MemSet(typeId, 0, FUNC_MAX_ARGS * sizeof(Oid)); typeId[0] = OIDOID; /* operator OID */ typeId[1] = OIDOID; /* relation OID */ typeId[2] = INT2OID; /* attribute number */ typeId[3] = 0; /* value - can be any type */ typeId[4] = INT4OID; /* flags - left or right selectivity */ - tup = SearchSysCacheTuple(PROCNAME, - PointerGetDatum(restrictionName), - Int32GetDatum(5), - PointerGetDatum(typeId), - 0); - if (!HeapTupleIsValid(tup)) + + restOid = GetSysCacheOid(PROCNAME, + PointerGetDatum(restrictionName), + Int32GetDatum(5), + PointerGetDatum(typeId), + 0); + if (!OidIsValid(restOid)) func_error("OperatorDef", restrictionName, 5, typeId, NULL); - values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(tup->t_data->t_oid); + values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(restOid); } else values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(InvalidOid); @@ -619,6 +623,8 @@ OperatorDef(char *operatorName, */ if (joinName) { /* optional */ + Oid joinOid; + MemSet(typeId, 0, FUNC_MAX_ARGS * sizeof(Oid)); typeId[0] = OIDOID; /* operator OID */ typeId[1] = OIDOID; /* relation OID 1 */ @@ -626,15 +632,15 @@ OperatorDef(char *operatorName, typeId[3] = OIDOID; /* relation OID 2 */ typeId[4] = INT2OID; /* attribute number 2 */ - tup = SearchSysCacheTuple(PROCNAME, - PointerGetDatum(joinName), - Int32GetDatum(5), - PointerGetDatum(typeId), - 0); - if (!HeapTupleIsValid(tup)) + joinOid = GetSysCacheOid(PROCNAME, + PointerGetDatum(joinName), + Int32GetDatum(5), + PointerGetDatum(typeId), + 0); + if (!OidIsValid(joinOid)) func_error("OperatorDef", joinName, 5, typeId, NULL); - values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(tup->t_data->t_oid); + values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(joinOid); } else values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(InvalidOid); diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index 26861047b24..9d3ce5c50d6 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.49 2000/10/07 00:58:15 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.50 2000/11/16 22:30:17 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -71,7 +71,7 @@ ProcedureCreate(char *procedureName, Oid toid; NameData procname; TupleDesc tupDesc; - Oid retval; + Oid retval; /* ---------------- * sanity checks @@ -80,15 +80,12 @@ ProcedureCreate(char *procedureName, Assert(PointerIsValid(prosrc)); Assert(PointerIsValid(probin)); - tup = SearchSysCacheTuple(LANGNAME, - PointerGetDatum(languageName), - 0, 0, 0); - - if (!HeapTupleIsValid(tup)) + languageObjectId = GetSysCacheOid(LANGNAME, + PointerGetDatum(languageName), + 0, 0, 0); + if (!OidIsValid(languageObjectId)) elog(ERROR, "ProcedureCreate: no such language '%s'", languageName); - languageObjectId = tup->t_data->t_oid; - parameterCount = 0; MemSet(typev, 0, FUNC_MAX_ARGS * sizeof(Oid)); foreach(x, argList) @@ -124,13 +121,12 @@ ProcedureCreate(char *procedureName, typev[parameterCount++] = toid; } - tup = SearchSysCacheTuple(PROCNAME, - PointerGetDatum(procedureName), - UInt16GetDatum(parameterCount), - PointerGetDatum(typev), - 0); - - if (HeapTupleIsValid(tup)) + /* Check for duplicate definition */ + if (SearchSysCacheExists(PROCNAME, + PointerGetDatum(procedureName), + UInt16GetDatum(parameterCount), + PointerGetDatum(typev), + 0)) elog(ERROR, "ProcedureCreate: procedure %s already exists with same arguments", procedureName); @@ -161,12 +157,12 @@ ProcedureCreate(char *procedureName, prosrctext = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(prosrc))); - tup = SearchSysCacheTuple(PROSRC, - PointerGetDatum(prosrctext), - 0, 0, 0); + retval = GetSysCacheOid(PROSRC, + PointerGetDatum(prosrctext), + 0, 0, 0); pfree(prosrctext); - if (HeapTupleIsValid(tup)) - return tup->t_data->t_oid; + if (OidIsValid(retval)) + return retval; #else elog(ERROR, "lookup for procedure by source needs fix (Jan)"); #endif /* SETS_FIXED */ @@ -351,7 +347,7 @@ checkretval(Oid rettype, List *queryTreeList) List *tlist; List *tlistitem; int tlistlen; - Type typ; + Oid typerelid; Resdom *resnode; Relation reln; Oid relid; @@ -375,11 +371,9 @@ checkretval(Oid rettype, List *queryTreeList) } /* by here, the function is declared to return some type */ - if ((typ = typeidType(rettype)) == NULL) - elog(ERROR, "can't find return type %u for function", rettype); - if (cmd != CMD_SELECT) - elog(ERROR, "function declared to return %s, but final query is not a SELECT", typeTypeName(typ)); + elog(ERROR, "function declared to return %s, but final query is not a SELECT", + typeidTypeName(rettype)); /* * Count the non-junk entries in the result targetlist. @@ -390,14 +384,17 @@ checkretval(Oid rettype, List *queryTreeList) * For base-type returns, the target list should have exactly one entry, * and its type should agree with what the user declared. */ - if (typeTypeRelid(typ) == InvalidOid) + typerelid = typeidTypeRelid(rettype); + if (typerelid == InvalidOid) { if (tlistlen != 1) - elog(ERROR, "function declared to return %s returns multiple columns in final SELECT", typeTypeName(typ)); + elog(ERROR, "function declared to return %s returns multiple columns in final SELECT", + typeidTypeName(rettype)); resnode = (Resdom *) ((TargetEntry *) lfirst(tlist))->resdom; if (resnode->restype != rettype) - elog(ERROR, "return type mismatch in function: declared to return %s, returns %s", typeTypeName(typ), typeidTypeName(resnode->restype)); + elog(ERROR, "return type mismatch in function: declared to return %s, returns %s", + typeidTypeName(rettype), typeidTypeName(resnode->restype)); return; } @@ -422,12 +419,13 @@ checkretval(Oid rettype, List *queryTreeList) * declared return type, and be sure that attributes 1 .. n in the target * list match the declared types. */ - reln = heap_open(typeTypeRelid(typ), AccessShareLock); + reln = heap_open(typerelid, AccessShareLock); relid = reln->rd_id; relnatts = reln->rd_rel->relnatts; if (tlistlen != relnatts) - elog(ERROR, "function declared to return %s does not SELECT the right number of columns (%d)", typeTypeName(typ), relnatts); + elog(ERROR, "function declared to return %s does not SELECT the right number of columns (%d)", + typeidTypeName(rettype), relnatts); /* expect attributes 1 .. n in order */ i = 0; @@ -441,7 +439,7 @@ checkretval(Oid rettype, List *queryTreeList) tletype = exprType(tle->expr); if (tletype != reln->rd_att->attrs[i]->atttypid) elog(ERROR, "function declared to return %s returns %s instead of %s at column %d", - typeTypeName(typ), + typeidTypeName(rettype), typeidTypeName(tletype), typeidTypeName(reln->rd_att->attrs[i]->atttypid), i+1); @@ -450,7 +448,8 @@ checkretval(Oid rettype, List *queryTreeList) /* this shouldn't happen, but let's just check... */ if (i != relnatts) - elog(ERROR, "function declared to return %s does not SELECT the right number of columns (%d)", typeTypeName(typ), relnatts); + elog(ERROR, "function declared to return %s does not SELECT the right number of columns (%d)", + typeidTypeName(rettype), relnatts); heap_close(reln, AccessShareLock); } diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index 2e5970cfcc8..f1f306424f0 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.55 2000/08/21 17:22:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.56 2000/11/16 22:30:17 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -388,6 +388,8 @@ TypeCreate(char *typeName, for (j = 0; j < 4; ++j) { + Oid procOid; + procname = procs[j]; /* @@ -396,13 +398,13 @@ TypeCreate(char *typeName, */ MemSet(argList, 0, FUNC_MAX_ARGS * sizeof(Oid)); - tup = SearchSysCacheTuple(PROCNAME, - PointerGetDatum(procname), - Int32GetDatum(1), - PointerGetDatum(argList), - 0); + procOid = GetSysCacheOid(PROCNAME, + PointerGetDatum(procname), + Int32GetDatum(1), + PointerGetDatum(argList), + 0); - if (!HeapTupleIsValid(tup)) + if (!OidIsValid(procOid)) { /* @@ -428,17 +430,17 @@ TypeCreate(char *typeName, argList[1] = OIDOID; argList[2] = INT4OID; } - tup = SearchSysCacheTuple(PROCNAME, - PointerGetDatum(procname), - Int32GetDatum(nargs), - PointerGetDatum(argList), - 0); + procOid = GetSysCacheOid(PROCNAME, + PointerGetDatum(procname), + Int32GetDatum(nargs), + PointerGetDatum(argList), + 0); } - if (!HeapTupleIsValid(tup)) + if (!OidIsValid(procOid)) func_error("TypeCreate", procname, 1, argList, NULL); } - values[i++] = ObjectIdGetDatum(tup->t_data->t_oid); /* 11 - 14 */ + values[i++] = ObjectIdGetDatum(procOid); /* 11 - 14 */ } /* ---------------- @@ -536,41 +538,31 @@ TypeRename(const char *oldTypeName, const char *newTypeName) { Relation pg_type_desc; Relation idescs[Num_pg_type_indices]; - HeapTuple oldtup, - newtup; + HeapTuple tuple; pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock); - oldtup = SearchSysCacheTupleCopy(TYPENAME, - PointerGetDatum(oldTypeName), - 0, 0, 0); - - if (!HeapTupleIsValid(oldtup)) - { - heap_close(pg_type_desc, RowExclusiveLock); - elog(ERROR, "TypeRename: type %s not defined", oldTypeName); - } + tuple = SearchSysCacheCopy(TYPENAME, + PointerGetDatum(oldTypeName), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "TypeRename: type \"%s\" not defined", oldTypeName); - newtup = SearchSysCacheTuple(TYPENAME, - PointerGetDatum(newTypeName), - 0, 0, 0); - if (HeapTupleIsValid(newtup)) - { - heap_freetuple(oldtup); - heap_close(pg_type_desc, RowExclusiveLock); - elog(ERROR, "TypeRename: type %s already defined", newTypeName); - } + if (SearchSysCacheExists(TYPENAME, + PointerGetDatum(newTypeName), + 0, 0, 0)) + elog(ERROR, "TypeRename: type \"%s\" already defined", newTypeName); - namestrcpy(&(((Form_pg_type) GETSTRUCT(oldtup))->typname), newTypeName); + namestrcpy(&(((Form_pg_type) GETSTRUCT(tuple))->typname), newTypeName); - heap_update(pg_type_desc, &oldtup->t_self, oldtup, NULL); + heap_update(pg_type_desc, &tuple->t_self, tuple, NULL); /* update the system catalog indices */ CatalogOpenIndices(Num_pg_type_indices, Name_pg_type_indices, idescs); - CatalogIndexInsert(idescs, Num_pg_type_indices, pg_type_desc, oldtup); + CatalogIndexInsert(idescs, Num_pg_type_indices, pg_type_desc, tuple); CatalogCloseIndices(Num_pg_type_indices, idescs); - heap_freetuple(oldtup); + heap_freetuple(tuple); heap_close(pg_type_desc, RowExclusiveLock); } diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index a83a5b7c3ab..bc1a2b9918f 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.8 2000/10/16 17:08:05 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.9 2000/11/16 22:30:19 tgl Exp $ * *------------------------------------------------------------------------- @@ -58,8 +58,7 @@ static void del_stats(Oid relid, int attcnt, int *attnums); void analyze_rel(Oid relid, List *anal_cols2, int MESSAGE_LEVEL) { - HeapTuple tuple, - typetuple; + HeapTuple tuple; Relation onerel; int32 i; int attr_cnt, @@ -81,20 +80,26 @@ analyze_rel(Oid relid, List *anal_cols2, int MESSAGE_LEVEL) * Race condition -- if the pg_class tuple has gone away since the * last time we saw it, we don't need to vacuum it. */ - tuple = SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(relid), - 0, 0, 0); + tuple = SearchSysCache(RELOID, + ObjectIdGetDatum(relid), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + { + CommitTransactionCommand(); + return; + } /* * We can VACUUM ANALYZE any table except pg_statistic. * see update_relstats */ - if (!HeapTupleIsValid(tuple) || - strcmp(NameStr(((Form_pg_class) GETSTRUCT(tuple))->relname), - StatisticRelationName) == 0) + if (strcmp(NameStr(((Form_pg_class) GETSTRUCT(tuple))->relname), + StatisticRelationName) == 0) { + ReleaseSysCache(tuple); CommitTransactionCommand(); return; } + ReleaseSysCache(tuple); onerel = heap_open(relid, AccessShareLock); @@ -168,6 +173,7 @@ analyze_rel(Oid relid, List *anal_cols2, int MESSAGE_LEVEL) { pgopform = (Form_pg_operator) GETSTRUCT(func_operator); fmgr_info(pgopform->oprcode, &(stats->f_cmpeq)); + ReleaseSysCache(func_operator); } else stats->f_cmpeq.fn_addr = NULL; @@ -178,6 +184,7 @@ analyze_rel(Oid relid, List *anal_cols2, int MESSAGE_LEVEL) pgopform = (Form_pg_operator) GETSTRUCT(func_operator); fmgr_info(pgopform->oprcode, &(stats->f_cmplt)); stats->op_cmplt = oprid(func_operator); + ReleaseSysCache(func_operator); } else { @@ -190,17 +197,19 @@ analyze_rel(Oid relid, List *anal_cols2, int MESSAGE_LEVEL) { pgopform = (Form_pg_operator) GETSTRUCT(func_operator); fmgr_info(pgopform->oprcode, &(stats->f_cmpgt)); + ReleaseSysCache(func_operator); } else stats->f_cmpgt.fn_addr = NULL; - typetuple = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(stats->attr->atttypid), - 0, 0, 0); - if (HeapTupleIsValid(typetuple)) + tuple = SearchSysCache(TYPEOID, + ObjectIdGetDatum(stats->attr->atttypid), + 0, 0, 0); + if (HeapTupleIsValid(tuple)) { - stats->outfunc = ((Form_pg_type) GETSTRUCT(typetuple))->typoutput; - stats->typelem = ((Form_pg_type) GETSTRUCT(typetuple))->typelem; + stats->outfunc = ((Form_pg_type) GETSTRUCT(tuple))->typoutput; + stats->typelem = ((Form_pg_type) GETSTRUCT(tuple))->typelem; + ReleaseSysCache(tuple); } else { diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 6611f134727..77f7776f6d9 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.70 2000/10/03 03:11:13 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.71 2000/11/16 22:30:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -193,9 +193,7 @@ void Async_Listen(char *relname, int pid) { Relation lRel; - TupleDesc tdesc; - HeapTuple tuple, - newtup; + HeapTuple tuple; Datum values[Natts_pg_listener]; char nulls[Natts_pg_listener]; int i; @@ -205,13 +203,12 @@ Async_Listen(char *relname, int pid) elog(DEBUG, "Async_Listen: %s", relname); lRel = heap_openr(ListenerRelationName, AccessExclusiveLock); - tdesc = RelationGetDescr(lRel); /* Detect whether we are already listening on this relname */ - tuple = SearchSysCacheTuple(LISTENREL, Int32GetDatum(pid), - PointerGetDatum(relname), - 0, 0); - if (tuple != NULL) + if (SearchSysCacheExists(LISTENREL, + Int32GetDatum(pid), + PointerGetDatum(relname), + 0, 0)) { /* No need to scan the rest of the table */ heap_close(lRel, AccessExclusiveLock); @@ -235,18 +232,18 @@ Async_Listen(char *relname, int pid) values[i++] = (Datum) 0; /* no notifies pending */ tupDesc = lRel->rd_att; - newtup = heap_formtuple(tupDesc, values, nulls); - heap_insert(lRel, newtup); + tuple = heap_formtuple(tupDesc, values, nulls); + heap_insert(lRel, tuple); if (RelationGetForm(lRel)->relhasindex) { Relation idescs[Num_pg_listener_indices]; CatalogOpenIndices(Num_pg_listener_indices, Name_pg_listener_indices, idescs); - CatalogIndexInsert(idescs, Num_pg_listener_indices, lRel, newtup); + CatalogIndexInsert(idescs, Num_pg_listener_indices, lRel, tuple); CatalogCloseIndices(Num_pg_listener_indices, idescs); } - heap_freetuple(newtup); + heap_freetuple(tuple); heap_close(lRel, AccessExclusiveLock); @@ -296,11 +293,15 @@ Async_Unlisten(char *relname, int pid) lRel = heap_openr(ListenerRelationName, AccessExclusiveLock); /* Note we assume there can be only one matching tuple. */ - lTuple = SearchSysCacheTuple(LISTENREL, Int32GetDatum(pid), - PointerGetDatum(relname), - 0, 0); - if (lTuple != NULL) + lTuple = SearchSysCache(LISTENREL, + Int32GetDatum(pid), + PointerGetDatum(relname), + 0, 0); + if (HeapTupleIsValid(lTuple)) + { heap_delete(lRel, &lTuple->t_self, NULL); + ReleaseSysCache(lTuple); + } heap_close(lRel, AccessExclusiveLock); /* diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index c02bafc3227..5c263e4c26c 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.59 2000/11/08 22:09:57 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.60 2000/11/16 22:30:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -84,15 +84,16 @@ cluster(char *oldrelname, char *oldindexname) /* * Check that index is in fact an index on the given relation */ - tuple = SearchSysCacheTuple(INDEXRELID, - ObjectIdGetDatum(OIDOldIndex), - 0, 0, 0); + tuple = SearchSysCache(INDEXRELID, + ObjectIdGetDatum(OIDOldIndex), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "CLUSTER: no pg_index entry for index %u", OIDOldIndex); if (((Form_pg_index) GETSTRUCT(tuple))->indrelid != OIDOldHeap) elog(ERROR, "CLUSTER: \"%s\" is not an index for table \"%s\"", saveoldindexname, saveoldrelname); + ReleaseSysCache(tuple); /* Drop relcache refcnts, but do NOT give up the locks */ heap_close(OldHeap, NoLock); @@ -184,17 +185,17 @@ copy_index(Oid OIDOldIndex, Oid OIDNewHeap, char *NewIndexName) * To do this I get the info from pg_index, and add a new index with * a temporary name. */ - Old_pg_index_Tuple = SearchSysCacheTupleCopy(INDEXRELID, - ObjectIdGetDatum(OIDOldIndex), - 0, 0, 0); + Old_pg_index_Tuple = SearchSysCache(INDEXRELID, + ObjectIdGetDatum(OIDOldIndex), + 0, 0, 0); Assert(Old_pg_index_Tuple); Old_pg_index_Form = (Form_pg_index) GETSTRUCT(Old_pg_index_Tuple); indexInfo = BuildIndexInfo(Old_pg_index_Tuple); - Old_pg_index_relation_Tuple = SearchSysCacheTupleCopy(RELOID, - ObjectIdGetDatum(OIDOldIndex), - 0, 0, 0); + Old_pg_index_relation_Tuple = SearchSysCache(RELOID, + ObjectIdGetDatum(OIDOldIndex), + 0, 0, 0); Assert(Old_pg_index_relation_Tuple); Old_pg_index_relation_Form = (Form_pg_class) GETSTRUCT(Old_pg_index_relation_Tuple); @@ -209,6 +210,9 @@ copy_index(Oid OIDOldIndex, Oid OIDNewHeap, char *NewIndexName) setRelhasindex(OIDNewHeap, true); + ReleaseSysCache(Old_pg_index_Tuple); + ReleaseSysCache(Old_pg_index_relation_Tuple); + index_close(OldIndex); heap_close(NewHeap, NoLock); } diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c index 958469fa4e1..42f05f0761c 100644 --- a/src/backend/commands/command.c +++ b/src/backend/commands/command.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.111 2000/11/14 01:57:30 inoue Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.112 2000/11/16 22:30:19 tgl Exp $ * * NOTES * The PerformAddAttribute() code, like most of the relation @@ -274,13 +274,13 @@ AlterTableAddColumn(const char *relationName, attrdesc; Oid myrelid; HeapTuple reltup; + HeapTuple newreltup; HeapTuple attributeTuple; Form_pg_attribute attribute; FormData_pg_attribute attributeD; int i; int minattnum, maxatts; - HeapTuple tup; Relation idescs[Num_pg_attr_indices]; Relation ridescs[Num_pg_class_indices]; bool hasindex; @@ -359,9 +359,9 @@ AlterTableAddColumn(const char *relationName, rel = heap_openr(RelationRelationName, RowExclusiveLock); - reltup = SearchSysCacheTupleCopy(RELNAME, - PointerGetDatum(relationName), - 0, 0, 0); + reltup = SearchSysCache(RELNAME, + PointerGetDatum(relationName), + 0, 0, 0); if (!HeapTupleIsValid(reltup)) elog(ERROR, "ALTER TABLE: relation \"%s\" not found", @@ -371,10 +371,8 @@ AlterTableAddColumn(const char *relationName, * XXX is the following check sufficient? */ if (((Form_pg_class) GETSTRUCT(reltup))->relkind != RELKIND_RELATION) - { elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table", relationName); - } minattnum = ((Form_pg_class) GETSTRUCT(reltup))->relnatts; maxatts = minattnum + 1; @@ -407,12 +405,10 @@ AlterTableAddColumn(const char *relationName, char *typename; int attnelems; - tup = SearchSysCacheTuple(ATTNAME, - ObjectIdGetDatum(reltup->t_data->t_oid), - PointerGetDatum(colDef->colname), - 0, 0); - - if (HeapTupleIsValid(tup)) + if (SearchSysCacheExists(ATTNAME, + ObjectIdGetDatum(reltup->t_data->t_oid), + PointerGetDatum(colDef->colname), + 0, 0)) elog(ERROR, "ALTER TABLE: column name \"%s\" already exists in table \"%s\"", colDef->colname, relationName); @@ -430,13 +426,13 @@ AlterTableAddColumn(const char *relationName, else attnelems = 0; - typeTuple = SearchSysCacheTuple(TYPENAME, - PointerGetDatum(typename), - 0, 0, 0); - tform = (Form_pg_type) GETSTRUCT(typeTuple); - + typeTuple = SearchSysCache(TYPENAME, + PointerGetDatum(typename), + 0, 0, 0); if (!HeapTupleIsValid(typeTuple)) elog(ERROR, "ALTER TABLE: type \"%s\" does not exist", typename); + tform = (Form_pg_type) GETSTRUCT(typeTuple); + namestrcpy(&(attribute->attname), colDef->colname); attribute->atttypid = typeTuple->t_data->t_oid; attribute->attlen = tform->typlen; @@ -453,6 +449,8 @@ AlterTableAddColumn(const char *relationName, attribute->atthasdef = (colDef->raw_default != NULL || colDef->cooked_default != NULL); + ReleaseSysCache(typeTuple); + heap_insert(attrdesc, attributeTuple); if (hasindex) CatalogIndexInsert(idescs, @@ -466,15 +464,21 @@ AlterTableAddColumn(const char *relationName, heap_close(attrdesc, RowExclusiveLock); - ((Form_pg_class) GETSTRUCT(reltup))->relnatts = maxatts; - heap_update(rel, &reltup->t_self, reltup, NULL); + /* + * Update number of attributes in pg_class tuple + */ + newreltup = heap_copytuple(reltup); + + ((Form_pg_class) GETSTRUCT(newreltup))->relnatts = maxatts; + heap_update(rel, &newreltup->t_self, newreltup, NULL); /* keep catalog indices current */ CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs); - CatalogIndexInsert(ridescs, Num_pg_class_indices, rel, reltup); + CatalogIndexInsert(ridescs, Num_pg_class_indices, rel, newreltup); CatalogCloseIndices(Num_pg_class_indices, ridescs); - heap_freetuple(reltup); + heap_freetuple(newreltup); + ReleaseSysCache(reltup); heap_close(rel, NoLock); @@ -555,11 +559,10 @@ AlterTableAlterColumn(const char *relationName, /* * get the number of the attribute */ - tuple = SearchSysCacheTuple(ATTNAME, - ObjectIdGetDatum(myrelid), - PointerGetDatum(colName), - 0, 0); - + tuple = SearchSysCache(ATTNAME, + ObjectIdGetDatum(myrelid), + PointerGetDatum(colName), + 0, 0); if (!HeapTupleIsValid(tuple)) { heap_close(rel, AccessExclusiveLock); @@ -568,6 +571,7 @@ AlterTableAlterColumn(const char *relationName, } attnum = ((Form_pg_attribute) GETSTRUCT(tuple))->attnum; + ReleaseSysCache(tuple); if (newDefault) /* SET DEFAULT */ { @@ -595,7 +599,6 @@ AlterTableAlterColumn(const char *relationName, Relation attr_rel; ScanKeyData scankeys[3]; HeapScanDesc scan; - HeapTuple tuple; attr_rel = heap_openr(AttributeRelationName, AccessExclusiveLock); ScanKeyEntryInitialize(&scankeys[0], 0x0, @@ -867,10 +870,11 @@ RemoveColumnReferences(Oid reloid, int attnum, bool checkonly, HeapTuple reltup) } else { - htup = SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(index->indexrelid), - 0, 0, 0); + htup = SearchSysCache(RELOID, + ObjectIdGetDatum(index->indexrelid), + 0, 0, 0); RemoveIndex(NameStr(((Form_pg_class) GETSTRUCT(htup))->relname)); + ReleaseSysCache(htup); } break; } @@ -941,18 +945,19 @@ AlterTableDropColumn(const char *relationName, if (length(find_all_inheritors(myrelid)) > 1) elog(ERROR, "ALTER TABLE: cannot drop a column on table that is inherited from"); - /* * lock the pg_class tuple for update */ - reltup = SearchSysCacheTuple(RELNAME, PointerGetDatum(relationName), - 0, 0, 0); - + rel = heap_openr(RelationRelationName, RowExclusiveLock); + reltup = SearchSysCache(RELNAME, + PointerGetDatum(relationName), + 0, 0, 0); if (!HeapTupleIsValid(reltup)) elog(ERROR, "ALTER TABLE: relation \"%s\" not found", relationName); - rel = heap_openr(RelationRelationName, RowExclusiveLock); classtuple.t_self = reltup->t_self; + ReleaseSysCache(reltup); + switch (heap_mark4update(rel, &classtuple, &buffer)) { case HeapTupleSelfUpdated: @@ -976,19 +981,21 @@ AlterTableDropColumn(const char *relationName, attrdesc = heap_openr(AttributeRelationName, RowExclusiveLock); /* - * Get the target pg_attribute tuple + * Get the target pg_attribute tuple and make a modifiable copy */ - tup = SearchSysCacheTupleCopy(ATTNAME, - ObjectIdGetDatum(reltup->t_data->t_oid), - PointerGetDatum(colName), 0, 0); + tup = SearchSysCacheCopy(ATTNAME, + ObjectIdGetDatum(reltup->t_data->t_oid), + PointerGetDatum(colName), + 0, 0); if (!HeapTupleIsValid(tup)) elog(ERROR, "ALTER TABLE: column name \"%s\" doesn't exist in table \"%s\"", colName, relationName); attribute = (Form_pg_attribute) GETSTRUCT(tup); - if (attribute->attnum <= 0) - elog(ERROR, "ALTER TABLE: column name \"%s\" was already dropped", colName); attnum = attribute->attnum; + if (attnum <= 0) + elog(ERROR, "ALTER TABLE: column name \"%s\" was already dropped", + colName); attoid = tup->t_data->t_oid; /* @@ -1226,10 +1233,9 @@ AlterTableAddConstraint(char *relationName, int count; List *indexoidlist, *indexoidscan; - Form_pg_index indexStruct = NULL; Form_pg_attribute *rel_attrs = NULL; - int i; - int found=0; + int i; + bool found = false; if (get_temp_rel_by_username(fkconstraint->pktable_name)!=NULL && get_temp_rel_by_username(relationName)==NULL) { @@ -1264,42 +1270,50 @@ AlterTableAddConstraint(char *relationName, indexoidlist = RelationGetIndexList(pkrel); foreach(indexoidscan, indexoidlist) + { + Oid indexoid = lfirsti(indexoidscan); + HeapTuple indexTuple; + Form_pg_index indexStruct; + + indexTuple = SearchSysCache(INDEXRELID, + ObjectIdGetDatum(indexoid), + 0, 0, 0); + if (!HeapTupleIsValid(indexTuple)) + elog(ERROR, "transformFkeyGetPrimaryKey: index %u not found", + indexoid); + indexStruct = (Form_pg_index) GETSTRUCT(indexTuple); + + if (indexStruct->indisunique) { - Oid indexoid = lfirsti(indexoidscan); - HeapTuple indexTuple; - List *attrl; - indexTuple = SearchSysCacheTuple(INDEXRELID, - ObjectIdGetDatum(indexoid), - 0, 0, 0); - if (!HeapTupleIsValid(indexTuple)) - elog(ERROR, "transformFkeyGetPrimaryKey: index %u not found", - indexoid); - indexStruct = (Form_pg_index) GETSTRUCT(indexTuple); - - if (indexStruct->indisunique) { - /* go through the fkconstraint->pk_attrs list */ - foreach(attrl, fkconstraint->pk_attrs) { - Ident *attr=lfirst(attrl); - found=0; - for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++) + List *attrl; + + /* go through the fkconstraint->pk_attrs list */ + foreach(attrl, fkconstraint->pk_attrs) + { + Ident *attr=lfirst(attrl); + found = false; + for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++) + { + int pkattno = indexStruct->indkey[i]; + if (pkattno>0) { - int pkattno = indexStruct->indkey[i]; - if (pkattno>0) { - char *name = NameStr(rel_attrs[pkattno-1]->attname); - if (strcmp(name, attr->name)==0) { - found=1; - break; - } + char *name = NameStr(rel_attrs[pkattno-1]->attname); + if (strcmp(name, attr->name)==0) + { + found = true; + break; } } - if (!found) - break; } + if (!found) + break; } - if (found) - break; - indexStruct = NULL; } + ReleaseSysCache(indexTuple); + if (found) + break; + } + if (!found) elog(ERROR, "UNIQUE constraint matching given keys for referenced table \"%s\" not found", fkconstraint->pktable_name); @@ -1309,17 +1323,18 @@ AlterTableAddConstraint(char *relationName, rel_attrs = rel->rd_att->attrs; if (fkconstraint->fk_attrs!=NIL) { - int found=0; List *fkattrs; Ident *fkattr; + + found = false; foreach(fkattrs, fkconstraint->fk_attrs) { - int count=0; - found=0; + int count; + found = false; fkattr=lfirst(fkattrs); - for (; count < rel->rd_att->natts; count++) { + for (count = 0; count < rel->rd_att->natts; count++) { char *name = NameStr(rel->rd_att->attrs[count]->attname); if (strcmp(name, fkattr->name)==0) { - found=1; + found = true; break; } } @@ -1441,20 +1456,22 @@ AlterTableOwner(const char *relationName, const char *newOwnerName) /* * look up the new owner in pg_shadow and get the sysid */ - tuple = SearchSysCacheTuple(SHADOWNAME, PointerGetDatum(newOwnerName), - 0, 0, 0); + tuple = SearchSysCache(SHADOWNAME, + PointerGetDatum(newOwnerName), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "ALTER TABLE: user \"%s\" not found", newOwnerName); - newOwnerSysid = ((Form_pg_shadow) GETSTRUCT(tuple))->usesysid; + ReleaseSysCache(tuple); /* - * find the table's entry in pg_class and lock it for writing + * find the table's entry in pg_class and make a modifiable copy */ class_rel = heap_openr(RelationRelationName, RowExclusiveLock); - tuple = SearchSysCacheTupleCopy(RELNAME, PointerGetDatum(relationName), - 0, 0, 0); + tuple = SearchSysCacheCopy(RELNAME, + PointerGetDatum(relationName), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "ALTER TABLE: relation \"%s\" not found", relationName); @@ -1525,13 +1542,15 @@ AlterTableCreateToastTable(const char *relationName, bool silent) */ class_rel = heap_openr(RelationRelationName, RowExclusiveLock); - reltup = SearchSysCacheTuple(RELNAME, PointerGetDatum(relationName), - 0, 0, 0); + reltup = SearchSysCache(RELNAME, + PointerGetDatum(relationName), + 0, 0, 0); if (!HeapTupleIsValid(reltup)) elog(ERROR, "ALTER TABLE: relation \"%s\" not found", relationName); - classtuple.t_self = reltup->t_self; + ReleaseSysCache(reltup); + switch (heap_mark4update(class_rel, &classtuple, &buffer)) { case HeapTupleSelfUpdated: diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index bff2b897c6e..8ab997831b9 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -276,7 +276,6 @@ DeleteComments(Oid oid) static void CommentRelation(int reltype, char *relname, char *comment) { - HeapTuple reltuple; Oid oid; char relkind; @@ -288,17 +287,20 @@ CommentRelation(int reltype, char *relname, char *comment) /*** Now, attempt to find the oid in the cached version of pg_class ***/ - reltuple = SearchSysCacheTuple(RELNAME, PointerGetDatum(relname), - 0, 0, 0); + reltuple = SearchSysCache(RELNAME, + PointerGetDatum(relname), + 0, 0, 0); if (!HeapTupleIsValid(reltuple)) elog(ERROR, "relation '%s' does not exist", relname); oid = reltuple->t_data->t_oid; - /*** Next, verify that the relation type matches the intent ***/ - relkind = ((Form_pg_class) GETSTRUCT(reltuple))->relkind; + ReleaseSysCache(reltuple); + + /*** Next, verify that the relation type matches the intent ***/ + switch (reltype) { case (INDEX): @@ -322,7 +324,6 @@ CommentRelation(int reltype, char *relname, char *comment) /*** Create the comments using the tuple's oid ***/ CreateComments(oid, comment); - } /*------------------------------------------------------------------ @@ -340,9 +341,7 @@ CommentRelation(int reltype, char *relname, char *comment) static void CommentAttribute(char *relname, char *attrname, char *comment) { - Relation relation; - HeapTuple attrtuple; Oid oid; /*** First, check object security ***/ @@ -350,15 +349,19 @@ CommentAttribute(char *relname, char *attrname, char *comment) if (!pg_ownercheck(GetUserId(), relname, RELNAME)) elog(ERROR, "you are not permitted to comment on class '%s\'", relname); - /*** Now, fetch the attribute oid from the system cache ***/ + /* Open the containing relation to ensure it won't go away meanwhile */ relation = heap_openr(relname, AccessShareLock); - attrtuple = SearchSysCacheTuple(ATTNAME, ObjectIdGetDatum(relation->rd_id), - PointerGetDatum(attrname), 0, 0); - if (!HeapTupleIsValid(attrtuple)) + + /*** Now, fetch the attribute oid from the system cache ***/ + + oid = GetSysCacheOid(ATTNAME, + ObjectIdGetDatum(relation->rd_id), + PointerGetDatum(attrname), + 0, 0); + if (!OidIsValid(oid)) elog(ERROR, "'%s' is not an attribute of class '%s'", attrname, relname); - oid = attrtuple->t_data->t_oid; /*** Call CreateComments() to create/drop the comments ***/ @@ -412,11 +415,13 @@ CommentDatabase(char *database, char *comment) /*** Now, fetch user information ***/ userid = GetUserId(); - usertuple = SearchSysCacheTuple(SHADOWSYSID, ObjectIdGetDatum(userid), - 0, 0, 0); + usertuple = SearchSysCache(SHADOWSYSID, + ObjectIdGetDatum(userid), + 0, 0, 0); if (!HeapTupleIsValid(usertuple)) elog(ERROR, "invalid user id %u", (unsigned) userid); superuser = ((Form_pg_shadow) GETSTRUCT(usertuple))->usesuper; + ReleaseSysCache(usertuple); /*** Allow if the userid matches the database dba or is a superuser ***/ @@ -452,8 +457,6 @@ CommentDatabase(char *database, char *comment) static void CommentRewrite(char *rule, char *comment) { - - HeapTuple rewritetuple; Oid oid; char *relation; int aclcheck; @@ -472,17 +475,15 @@ CommentRewrite(char *rule, char *comment) /*** Next, find the rule's oid ***/ - rewritetuple = SearchSysCacheTuple(RULENAME, PointerGetDatum(rule), - 0, 0, 0); - if (!HeapTupleIsValid(rewritetuple)) + oid = GetSysCacheOid(RULENAME, + PointerGetDatum(rule), + 0, 0, 0); + if (!OidIsValid(oid)) elog(ERROR, "rule '%s' does not exist", rule); - oid = rewritetuple->t_data->t_oid; - /*** Call CreateComments() to create/drop the comments ***/ CreateComments(oid, comment); - } /*------------------------------------------------------------------ @@ -499,8 +500,6 @@ CommentRewrite(char *rule, char *comment) static void CommentType(char *type, char *comment) { - - HeapTuple typetuple; Oid oid; /*** First, validate user ***/ @@ -515,17 +514,15 @@ CommentType(char *type, char *comment) /*** Next, find the type's oid ***/ - typetuple = SearchSysCacheTuple(TYPENAME, PointerGetDatum(type), - 0, 0, 0); - if (!HeapTupleIsValid(typetuple)) + oid = GetSysCacheOid(TYPENAME, + PointerGetDatum(type), + 0, 0, 0); + if (!OidIsValid(oid)) elog(ERROR, "type '%s' does not exist", type); - oid = typetuple->t_data->t_oid; - /*** Call CreateComments() to create/drop the comments ***/ CreateComments(oid, comment); - } /*------------------------------------------------------------------ @@ -543,7 +540,6 @@ CommentAggregate(char *aggregate, List *arguments, char *comment) { TypeName *aggtype = (TypeName *) lfirst(arguments); char *aggtypename = NULL; - HeapTuple aggtuple; Oid baseoid, oid; bool defined; @@ -580,9 +576,11 @@ CommentAggregate(char *aggregate, List *arguments, char *comment) /*** Now, attempt to find the actual tuple in pg_aggregate ***/ - aggtuple = SearchSysCacheTuple(AGGNAME, PointerGetDatum(aggregate), - ObjectIdGetDatum(baseoid), 0, 0); - if (!HeapTupleIsValid(aggtuple)) + oid = GetSysCacheOid(AGGNAME, + PointerGetDatum(aggregate), + ObjectIdGetDatum(baseoid), + 0, 0); + if (!OidIsValid(oid)) { if (aggtypename) { @@ -593,12 +591,9 @@ CommentAggregate(char *aggregate, List *arguments, char *comment) elog(ERROR, "aggregate '%s' does not exist", aggregate); } - oid = aggtuple->t_data->t_oid; - /*** Call CreateComments() to create/drop the comments ***/ CreateComments(oid, comment); - } /*------------------------------------------------------------------ @@ -615,8 +610,6 @@ CommentAggregate(char *aggregate, List *arguments, char *comment) static void CommentProc(char *function, List *arguments, char *comment) { - HeapTuple argtuple, - functuple; Oid oid, argoids[FUNC_MAX_ARGS]; int i, @@ -640,12 +633,11 @@ CommentProc(char *function, List *arguments, char *comment) argoids[i] = InvalidOid; else { - argtuple = SearchSysCacheTuple(TYPENAME, - PointerGetDatum(typnam), - 0, 0, 0); - if (!HeapTupleIsValid(argtuple)) + argoids[i] = GetSysCacheOid(TYPENAME, + PointerGetDatum(typnam), + 0, 0, 0); + if (!OidIsValid(argoids[i])) elog(ERROR, "CommentProc: type '%s' not found", typnam); - argoids[i] = argtuple->t_data->t_oid; } } @@ -659,14 +651,14 @@ CommentProc(char *function, List *arguments, char *comment) /*** Now, find the corresponding oid for this procedure ***/ - functuple = SearchSysCacheTuple(PROCNAME, PointerGetDatum(function), - Int32GetDatum(argcount), - PointerGetDatum(argoids), 0); - if (!HeapTupleIsValid(functuple)) + oid = GetSysCacheOid(PROCNAME, + PointerGetDatum(function), + Int32GetDatum(argcount), + PointerGetDatum(argoids), + 0); + if (!OidIsValid(oid)) func_error("CommentProc", function, argcount, argoids, NULL); - oid = functuple->t_data->t_oid; - /*** Call CreateComments() to create/drop the comments ***/ CreateComments(oid, comment); @@ -738,10 +730,11 @@ CommentOperator(char *opername, List *arguments, char *comment) /*** Attempt to fetch the operator oid ***/ - optuple = SearchSysCacheTupleCopy(OPERNAME, PointerGetDatum(opername), - ObjectIdGetDatum(leftoid), - ObjectIdGetDatum(rightoid), - CharGetDatum(oprtype)); + optuple = SearchSysCache(OPERNAME, + PointerGetDatum(opername), + ObjectIdGetDatum(leftoid), + ObjectIdGetDatum(rightoid), + CharGetDatum(oprtype)); if (!HeapTupleIsValid(optuple)) elog(ERROR, "operator '%s' does not exist", opername); @@ -764,6 +757,8 @@ CommentOperator(char *opername, List *arguments, char *comment) if (oid == InvalidOid) elog(ERROR, "operator '%s' does not have an underlying function", opername); + ReleaseSysCache(optuple); + /*** Call CreateComments() to create/drop the comments ***/ CreateComments(oid, comment); diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 2877999500c..bbbb5aa2cfc 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.123 2000/11/12 00:36:56 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.124 2000/11/16 22:30:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -48,9 +48,9 @@ static void CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null_print); static void CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null_print); static Oid GetOutputFunction(Oid type); -static Oid GetTypeElement(Oid type); static Oid GetInputFunction(Oid type); -static Oid IsTypeByVal(Oid type); +static Oid GetTypeElement(Oid type); +static bool IsTypeByVal(Oid type); static void CopyReadNewline(FILE *fp, int *newline); static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_print); @@ -669,7 +669,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, continue; } #endif /* _DROP_COLUMN_HACK__ */ - byval[i] = (bool) IsTypeByVal(attr[i]->atttypid); + byval[i] = IsTypeByVal(attr[i]->atttypid); } lineno = 0; @@ -893,65 +893,64 @@ static Oid GetOutputFunction(Oid type) { HeapTuple typeTuple; - - typeTuple = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(type), - 0, 0, 0); - - if (HeapTupleIsValid(typeTuple)) - return (int) ((Form_pg_type) GETSTRUCT(typeTuple))->typoutput; - - elog(ERROR, "GetOutputFunction: Cache lookup of type %u failed", type); - return InvalidOid; + Oid result; + + typeTuple = SearchSysCache(TYPEOID, + ObjectIdGetDatum(type), + 0, 0, 0); + if (!HeapTupleIsValid(typeTuple)) + elog(ERROR, "GetOutputFunction: Cache lookup of type %u failed", type); + result = ((Form_pg_type) GETSTRUCT(typeTuple))->typoutput; + ReleaseSysCache(typeTuple); + return result; } static Oid -GetTypeElement(Oid type) +GetInputFunction(Oid type) { HeapTuple typeTuple; - - typeTuple = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(type), - 0, 0, 0); - - if (HeapTupleIsValid(typeTuple)) - return (int) ((Form_pg_type) GETSTRUCT(typeTuple))->typelem; - - elog(ERROR, "GetOutputFunction: Cache lookup of type %u failed", type); - return InvalidOid; + Oid result; + + typeTuple = SearchSysCache(TYPEOID, + ObjectIdGetDatum(type), + 0, 0, 0); + if (!HeapTupleIsValid(typeTuple)) + elog(ERROR, "GetInputFunction: Cache lookup of type %u failed", type); + result = ((Form_pg_type) GETSTRUCT(typeTuple))->typinput; + ReleaseSysCache(typeTuple); + return result; } static Oid -GetInputFunction(Oid type) +GetTypeElement(Oid type) { HeapTuple typeTuple; - - typeTuple = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(type), - 0, 0, 0); - - if (HeapTupleIsValid(typeTuple)) - return (int) ((Form_pg_type) GETSTRUCT(typeTuple))->typinput; - - elog(ERROR, "GetInputFunction: Cache lookup of type %u failed", type); - return InvalidOid; + Oid result; + + typeTuple = SearchSysCache(TYPEOID, + ObjectIdGetDatum(type), + 0, 0, 0); + if (!HeapTupleIsValid(typeTuple)) + elog(ERROR, "GetTypeElement: Cache lookup of type %u failed", type); + result = ((Form_pg_type) GETSTRUCT(typeTuple))->typelem; + ReleaseSysCache(typeTuple); + return result; } -static Oid +static bool IsTypeByVal(Oid type) { HeapTuple typeTuple; - - typeTuple = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(type), - 0, 0, 0); - - if (HeapTupleIsValid(typeTuple)) - return (int) ((Form_pg_type) GETSTRUCT(typeTuple))->typbyval; - - elog(ERROR, "GetInputFunction: Cache lookup of type %u failed", type); - - return InvalidOid; + bool result; + + typeTuple = SearchSysCache(TYPEOID, + ObjectIdGetDatum(type), + 0, 0, 0); + if (!HeapTupleIsValid(typeTuple)) + elog(ERROR, "IsTypeByVal: Cache lookup of type %u failed", type); + result = ((Form_pg_type) GETSTRUCT(typeTuple))->typbyval; + ReleaseSysCache(typeTuple); + return result; } diff --git a/src/backend/commands/creatinh.c b/src/backend/commands/creatinh.c index a1d45d170a1..970782d6da3 100644 --- a/src/backend/commands/creatinh.c +++ b/src/backend/commands/creatinh.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.66 2000/11/13 09:16:55 inoue Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.67 2000/11/16 22:30:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -408,11 +408,14 @@ MergeAttributes(List *schema, List *supers, List **supconstr) * form name, type and constraints */ attributeName = NameStr(attribute->attname); - tuple = SearchSysCacheTuple(TYPEOID, + tuple = SearchSysCache(TYPEOID, ObjectIdGetDatum(attribute->atttypid), - 0, 0, 0); - Assert(HeapTupleIsValid(tuple)); - attributeType = NameStr(((Form_pg_type) GETSTRUCT(tuple))->typname); + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "CREATE TABLE: cache lookup failed for type %u", + attribute->atttypid); + attributeType = pstrdup(NameStr(((Form_pg_type) GETSTRUCT(tuple))->typname)); + ReleaseSysCache(tuple); /* * check validity @@ -554,22 +557,25 @@ StoreCatalogInheritance(Oid relationId, List *supers) idList = NIL; foreach(entry, supers) { + Oid entryOid; Datum datum[Natts_pg_inherits]; char nullarr[Natts_pg_inherits]; - tuple = SearchSysCacheTuple(RELNAME, + entryOid = GetSysCacheOid(RELNAME, PointerGetDatum(strVal(lfirst(entry))), - 0, 0, 0); - AssertArg(HeapTupleIsValid(tuple)); + 0, 0, 0); + if (!OidIsValid(entryOid)) + elog(ERROR, "StoreCatalogInheritance: cache lookup failed for relation \"%s\"", + strVal(lfirst(entry))); /* * build idList for use below */ - idList = lappendi(idList, tuple->t_data->t_oid); + idList = lappendi(idList, entryOid); - datum[0] = ObjectIdGetDatum(relationId); /* inhrel */ - datum[1] = ObjectIdGetDatum(tuple->t_data->t_oid); /* inhparent */ - datum[2] = Int16GetDatum(seqNumber); /* inhseqno */ + datum[0] = ObjectIdGetDatum(relationId); /* inhrel */ + datum[1] = ObjectIdGetDatum(entryOid); /* inhparent */ + datum[2] = Int16GetDatum(seqNumber); /* inhseqno */ nullarr[0] = ' '; nullarr[1] = ' '; @@ -624,11 +630,10 @@ StoreCatalogInheritance(Oid relationId, List *supers) for (number = 1;; number += 1) { - tuple = SearchSysCacheTuple(INHRELID, - ObjectIdGetDatum(id), - Int16GetDatum(number), - 0, 0); - + tuple = SearchSysCache(INHRELID, + ObjectIdGetDatum(id), + Int16GetDatum(number), + 0, 0); if (!HeapTupleIsValid(tuple)) break; @@ -636,6 +641,8 @@ StoreCatalogInheritance(Oid relationId, List *supers) GETSTRUCT(tuple))->inhparent, NIL); + ReleaseSysCache(tuple); + current = lnext(current); } lnext(current) = next; @@ -746,35 +753,28 @@ checkAttrExists(const char *attributeName, const char *attributeType, List *sche static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass) { - Relation relationRelation; - HeapTuple tuple; - Relation idescs[Num_pg_class_indices]; - - /* - * Lock a relation given its Oid. Go to the RelationRelation (i.e. - * pg_relation), find the appropriate tuple, and add the specified - * lock to it. - */ - relationRelation = heap_openr(RelationRelationName, RowExclusiveLock); - tuple = SearchSysCacheTupleCopy(RELOID, - ObjectIdGetDatum(relationId), - 0, 0, 0) -; - Assert(HeapTupleIsValid(tuple)); - - ((Form_pg_class) GETSTRUCT(tuple))->relhassubclass = relhassubclass; - heap_update(relationRelation, &tuple->t_self, tuple, NULL); - - /* keep the catalog indices up to date */ - CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs); - CatalogIndexInsert(idescs, Num_pg_class_indices, relationRelation, tuple -); - CatalogCloseIndices(Num_pg_class_indices, idescs); - - heap_freetuple(tuple); - heap_close(relationRelation, RowExclusiveLock); -} + Relation relationRelation; + HeapTuple tuple; + Relation idescs[Num_pg_class_indices]; + /* + * Fetch a modifiable copy of the tuple, modify it, update pg_class. + */ + relationRelation = heap_openr(RelationRelationName, RowExclusiveLock); + tuple = SearchSysCacheCopy(RELOID, + ObjectIdGetDatum(relationId), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "setRelhassubclassInRelation: cache lookup failed for relation %u", relationId); + ((Form_pg_class) GETSTRUCT(tuple))->relhassubclass = relhassubclass; + heap_update(relationRelation, &tuple->t_self, tuple, NULL); + /* keep the catalog indices up to date */ + CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs); + CatalogIndexInsert(idescs, Num_pg_class_indices, relationRelation, tuple); + CatalogCloseIndices(Num_pg_class_indices, idescs); + heap_freetuple(tuple); + heap_close(relationRelation, RowExclusiveLock); +} diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 70fd952db63..464a9b68fb2 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.67 2000/11/14 18:37:41 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.68 2000/11/16 22:30:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -445,9 +445,9 @@ get_user_info(Oid use_sysid, bool *use_super, bool *use_createdb) { HeapTuple utup; - utup = SearchSysCacheTuple(SHADOWSYSID, - ObjectIdGetDatum(use_sysid), - 0, 0, 0); + utup = SearchSysCache(SHADOWSYSID, + ObjectIdGetDatum(use_sysid), + 0, 0, 0); if (!HeapTupleIsValid(utup)) return false; @@ -457,6 +457,8 @@ get_user_info(Oid use_sysid, bool *use_super, bool *use_createdb) if (use_createdb) *use_createdb = ((Form_pg_shadow) GETSTRUCT(utup))->usecreatedb; + ReleaseSysCache(utup); + return true; } diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c index a33d155db9f..9d681a4a50f 100644 --- a/src/backend/commands/define.c +++ b/src/backend/commands/define.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.47 2000/10/07 00:58:16 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.48 2000/11/16 22:30:18 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -277,10 +277,9 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest) Form_pg_language languageStruct; /* Lookup the language in the system cache */ - languageTuple = SearchSysCacheTuple(LANGNAME, - PointerGetDatum(languageName), - 0, 0, 0); - + languageTuple = SearchSysCache(LANGNAME, + PointerGetDatum(languageName), + 0, 0, 0); if (!HeapTupleIsValid(languageTuple)) elog(ERROR, "Unrecognized language specified in a CREATE FUNCTION: " @@ -299,12 +298,12 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest) * be defined by postgres superusers only */ if (!languageStruct->lanpltrusted && !superuser()) - { elog(ERROR, "Only users with Postgres superuser privilege " "are permitted to create a function in the '%s' " "language.", languageName); - } + + ReleaseSysCache(languageTuple); } /* diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index fff6d569753..788701b20fe 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.40 2000/11/08 22:09:57 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.41 2000/11/16 22:30:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -86,7 +86,6 @@ DefineIndex(char *heapRelationName, Oid relationId; IndexInfo *indexInfo; int numberOfAttributes; - HeapTuple tuple; List *cnfPred = NIL; bool lossy = false; List *pl; @@ -111,13 +110,12 @@ DefineIndex(char *heapRelationName, /* * compute access method id */ - tuple = SearchSysCacheTuple(AMNAME, - PointerGetDatum(accessMethodName), - 0, 0, 0); - if (!HeapTupleIsValid(tuple)) + accessMethodId = GetSysCacheOid(AMNAME, + PointerGetDatum(accessMethodName), + 0, 0, 0); + if (!OidIsValid(accessMethodId)) elog(ERROR, "DefineIndex: access method \"%s\" not found", accessMethodName); - accessMethodId = tuple->t_data->t_oid; /* * XXX Hardwired hacks to check for limitations on supported index types. @@ -239,21 +237,22 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable) /* * Get index's relation id and access method id from pg_class */ - tuple = SearchSysCacheTuple(RELNAME, - PointerGetDatum(indexRelationName), - 0, 0, 0); + tuple = SearchSysCache(RELNAME, + PointerGetDatum(indexRelationName), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "ExtendIndex: index \"%s\" not found", indexRelationName); indexId = tuple->t_data->t_oid; accessMethodId = ((Form_pg_class) GETSTRUCT(tuple))->relam; + ReleaseSysCache(tuple); /* * Extract info from the pg_index tuple for the index */ - tuple = SearchSysCacheTuple(INDEXRELID, - ObjectIdGetDatum(indexId), - 0, 0, 0); + tuple = SearchSysCache(INDEXRELID, + ObjectIdGetDatum(indexId), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "ExtendIndex: relation \"%s\" is not an index", indexRelationName); @@ -262,6 +261,7 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable) relationId = index->indrelid; indexInfo = BuildIndexInfo(tuple); oldPred = indexInfo->ii_Predicate; + ReleaseSysCache(tuple); if (oldPred == NULL) elog(ERROR, "ExtendIndex: \"%s\" is not a partial index", @@ -391,16 +391,16 @@ FuncIndexArgs(IndexInfo *indexInfo, HeapTuple tuple; Form_pg_attribute att; - tuple = SearchSysCacheTuple(ATTNAME, - ObjectIdGetDatum(relId), - PointerGetDatum(arg), - 0, 0); + tuple = SearchSysCache(ATTNAME, + ObjectIdGetDatum(relId), + PointerGetDatum(arg), + 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "DefineIndex: attribute \"%s\" not found", arg); att = (Form_pg_attribute) GETSTRUCT(tuple); - indexInfo->ii_KeyAttrNumbers[nargs] = att->attnum; argTypes[nargs] = att->atttypid; + ReleaseSysCache(tuple); nargs++; } @@ -465,10 +465,10 @@ NormIndexAttrs(IndexInfo *indexInfo, if (attribute->name == NULL) elog(ERROR, "missing attribute for define index"); - atttuple = SearchSysCacheTupleCopy(ATTNAME, - ObjectIdGetDatum(relId), - PointerGetDatum(attribute->name), - 0, 0); + atttuple = SearchSysCache(ATTNAME, + ObjectIdGetDatum(relId), + PointerGetDatum(attribute->name), + 0, 0); if (!HeapTupleIsValid(atttuple)) elog(ERROR, "DefineIndex: attribute \"%s\" not found", attribute->name); @@ -479,7 +479,7 @@ NormIndexAttrs(IndexInfo *indexInfo, classOidP[attn] = GetAttrOpClass(attribute, attform->atttypid, accessMethodName, accessMethodId); - heap_freetuple(atttuple); + ReleaseSysCache(atttuple); attn++; } } @@ -507,13 +507,12 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType, doTypeCheck = false; } - tuple = SearchSysCacheTuple(CLANAME, - PointerGetDatum(attribute->class), - 0, 0, 0); - if (!HeapTupleIsValid(tuple)) + opClassId = GetSysCacheOid(CLANAME, + PointerGetDatum(attribute->class), + 0, 0, 0); + if (!OidIsValid(opClassId)) elog(ERROR, "DefineIndex: opclass \"%s\" not found", attribute->class); - opClassId = tuple->t_data->t_oid; /* * Assume the opclass is supported by this index access method @@ -532,10 +531,8 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType, scan = heap_beginscan(relation, false, SnapshotNow, 2, entry); if (! HeapTupleIsValid(tuple = heap_getnext(scan, 0))) - { elog(ERROR, "DefineIndex: opclass \"%s\" not supported by access method \"%s\"", attribute->class, accessMethodName); - } oprId = ((Form_pg_amop) GETSTRUCT(tuple))->amopopr; @@ -557,9 +554,9 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType, */ if (doTypeCheck) { - tuple = SearchSysCacheTuple(OPEROID, - ObjectIdGetDatum(oprId), - 0, 0, 0); + tuple = SearchSysCache(OPEROID, + ObjectIdGetDatum(oprId), + 0, 0, 0); if (HeapTupleIsValid(tuple)) { Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tuple); @@ -570,6 +567,7 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType, ! IS_BINARY_COMPATIBLE(attrType, opInputType)) elog(ERROR, "DefineIndex: opclass \"%s\" does not accept datatype \"%s\"", attribute->class, typeidTypeName(attrType)); + ReleaseSysCache(tuple); } } @@ -580,15 +578,18 @@ static char * GetDefaultOpClass(Oid atttypid) { HeapTuple tuple; + char *result; - tuple = SearchSysCacheTuple(CLADEFTYPE, - ObjectIdGetDatum(atttypid), - 0, 0, 0); + tuple = SearchSysCache(CLADEFTYPE, + ObjectIdGetDatum(atttypid), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) return NULL; - return DatumGetCString(DirectFunctionCall1(nameout, - NameGetDatum(&((Form_pg_opclass) GETSTRUCT(tuple))->opcname))); + result = pstrdup(NameStr(((Form_pg_opclass) GETSTRUCT(tuple))->opcname)); + + ReleaseSysCache(tuple); + return result; } /* @@ -605,21 +606,19 @@ RemoveIndex(char *name) { HeapTuple tuple; - tuple = SearchSysCacheTuple(RELNAME, - PointerGetDatum(name), - 0, 0, 0); - + tuple = SearchSysCache(RELNAME, + PointerGetDatum(name), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "index \"%s\" does not exist", name); if (((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_INDEX) - { elog(ERROR, "relation \"%s\" is of type \"%c\"", - name, - ((Form_pg_class) GETSTRUCT(tuple))->relkind); - } + name, ((Form_pg_class) GETSTRUCT(tuple))->relkind); index_drop(tuple->t_data->t_oid); + + ReleaseSysCache(tuple); } /* @@ -644,22 +643,20 @@ ReindexIndex(const char *name, bool force /* currently unused */ ) if (IsTransactionBlock()) elog(ERROR, "REINDEX cannot run inside a BEGIN/END block"); - tuple = SearchSysCacheTuple(RELNAME, - PointerGetDatum(name), - 0, 0, 0); - + tuple = SearchSysCache(RELNAME, + PointerGetDatum(name), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "index \"%s\" does not exist", name); if (((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_INDEX) - { elog(ERROR, "relation \"%s\" is of type \"%c\"", - name, - ((Form_pg_class) GETSTRUCT(tuple))->relkind); - } + name, ((Form_pg_class) GETSTRUCT(tuple))->relkind); if (!reindex_index(tuple->t_data->t_oid, force)) elog(NOTICE, "index \"%s\" wasn't reindexed", name); + + ReleaseSysCache(tuple); } /* @@ -684,22 +681,20 @@ ReindexTable(const char *name, bool force) if (IsTransactionBlock()) elog(ERROR, "REINDEX cannot run inside a BEGIN/END block"); - tuple = SearchSysCacheTuple(RELNAME, - PointerGetDatum(name), - 0, 0, 0); - + tuple = SearchSysCache(RELNAME, + PointerGetDatum(name), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "table \"%s\" does not exist", name); if (((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_RELATION) - { elog(ERROR, "relation \"%s\" is of type \"%c\"", - name, - ((Form_pg_class) GETSTRUCT(tuple))->relkind); - } + name, ((Form_pg_class) GETSTRUCT(tuple))->relkind); if (!reindex_relation(tuple->t_data->t_oid, force)) elog(NOTICE, "table \"%s\" wasn't reindexed", name); + + ReleaseSysCache(tuple); } /* diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index ec8aec7005f..5d4d3f09bf7 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -48,7 +48,6 @@ void CreateProceduralLanguage(CreatePLangStmt *stmt) { char languageName[NAMEDATALEN]; - HeapTuple langTup; HeapTuple procTup; Oid typev[FUNC_MAX_ARGS]; @@ -77,10 +76,9 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) */ case_translate_language_name(stmt->plname, languageName); - langTup = SearchSysCacheTuple(LANGNAME, - PointerGetDatum(languageName), - 0, 0, 0); - if (HeapTupleIsValid(langTup)) + if (SearchSysCacheExists(LANGNAME, + PointerGetDatum(languageName), + 0, 0, 0)) elog(ERROR, "Language %s already exists", languageName); /* ---------------- @@ -89,21 +87,17 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) * ---------------- */ memset(typev, 0, sizeof(typev)); - procTup = SearchSysCacheTuple(PROCNAME, - PointerGetDatum(stmt->plhandler), - Int32GetDatum(0), - PointerGetDatum(typev), - 0); + procTup = SearchSysCache(PROCNAME, + PointerGetDatum(stmt->plhandler), + Int32GetDatum(0), + PointerGetDatum(typev), + 0); if (!HeapTupleIsValid(procTup)) - { elog(ERROR, "PL handler function %s() doesn't exist", stmt->plhandler); - } if (((Form_pg_proc) GETSTRUCT(procTup))->prorettype != InvalidOid) - { elog(ERROR, "PL handler function %s() isn't of return type Opaque", stmt->plhandler); - } /* ---------------- * Insert the new language into pg_language @@ -123,6 +117,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) values[i++] = DirectFunctionCall1(textin, CStringGetDatum(stmt->plcompiler)); + ReleaseSysCache(procTup); + rel = heap_openr(LanguageRelationName, RowExclusiveLock); tupDesc = rel->rd_att; @@ -173,9 +169,9 @@ DropProceduralLanguage(DropPLangStmt *stmt) rel = heap_openr(LanguageRelationName, RowExclusiveLock); - langTup = SearchSysCacheTupleCopy(LANGNAME, - PointerGetDatum(languageName), - 0, 0, 0); + langTup = SearchSysCacheCopy(LANGNAME, + PointerGetDatum(languageName), + 0, 0, 0); if (!HeapTupleIsValid(langTup)) elog(ERROR, "Language %s doesn't exist", languageName); diff --git a/src/backend/commands/remove.c b/src/backend/commands/remove.c index a8ad2620ef7..fdcd0e7e744 100644 --- a/src/backend/commands/remove.c +++ b/src/backend/commands/remove.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.54 2000/10/16 17:08:05 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.55 2000/11/16 22:30:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -73,11 +73,11 @@ RemoveOperator(char *operatorName, /* operator name */ relation = heap_openr(OperatorRelationName, RowExclusiveLock); - tup = SearchSysCacheTupleCopy(OPERNAME, - PointerGetDatum(operatorName), - ObjectIdGetDatum(typeId1), - ObjectIdGetDatum(typeId2), - CharGetDatum(oprtype)); + tup = SearchSysCacheCopy(OPERNAME, + PointerGetDatum(operatorName), + ObjectIdGetDatum(typeId1), + ObjectIdGetDatum(typeId2), + CharGetDatum(oprtype)); if (HeapTupleIsValid(tup)) { @@ -254,14 +254,11 @@ RemoveType(char *typeName) /* type name to be removed */ relation = heap_openr(TypeRelationName, RowExclusiveLock); - tup = SearchSysCacheTuple(TYPENAME, - PointerGetDatum(typeName), - 0, 0, 0); + tup = SearchSysCache(TYPENAME, + PointerGetDatum(typeName), + 0, 0, 0); if (!HeapTupleIsValid(tup)) - { - heap_close(relation, RowExclusiveLock); elog(ERROR, "RemoveType: type '%s' does not exist", typeName); - } typeOid = tup->t_data->t_oid; @@ -271,19 +268,20 @@ RemoveType(char *typeName) /* type name to be removed */ heap_delete(relation, &tup->t_self, NULL); - /* Now, Delete the "array of" that type */ + ReleaseSysCache(tup); + + /* Also, delete the "array of" that type */ shadow_type = makeArrayTypeName(typeName); - tup = SearchSysCacheTuple(TYPENAME, - PointerGetDatum(shadow_type), - 0, 0, 0); + tup = SearchSysCache(TYPENAME, + PointerGetDatum(shadow_type), + 0, 0, 0); if (!HeapTupleIsValid(tup)) - { - heap_close(relation, RowExclusiveLock); elog(ERROR, "RemoveType: type '%s' does not exist", shadow_type); - } heap_delete(relation, &tup->t_self, NULL); + ReleaseSysCache(tup); + heap_close(relation, RowExclusiveLock); } @@ -321,12 +319,11 @@ RemoveFunction(char *functionName, /* function name to be removed */ argList[i] = InvalidOid; else { - tup = SearchSysCacheTuple(TYPENAME, - PointerGetDatum(typnam), - 0, 0, 0); - if (!HeapTupleIsValid(tup)) + argList[i] = GetSysCacheOid(TYPENAME, + PointerGetDatum(typnam), + 0, 0, 0); + if (!OidIsValid(argList[i])) elog(ERROR, "RemoveFunction: type '%s' not found", typnam); - argList[i] = tup->t_data->t_oid; } } @@ -337,11 +334,12 @@ RemoveFunction(char *functionName, /* function name to be removed */ } relation = heap_openr(ProcedureRelationName, RowExclusiveLock); - tup = SearchSysCacheTuple(PROCNAME, - PointerGetDatum(functionName), - Int32GetDatum(nargs), - PointerGetDatum(argList), - 0); + + tup = SearchSysCache(PROCNAME, + PointerGetDatum(functionName), + Int32GetDatum(nargs), + PointerGetDatum(argList), + 0); if (!HeapTupleIsValid(tup)) func_error("RemoveFunction", functionName, nargs, argList, NULL); @@ -359,6 +357,8 @@ RemoveFunction(char *functionName, /* function name to be removed */ heap_delete(relation, &tup->t_self, NULL); + ReleaseSysCache(tup); + heap_close(relation, RowExclusiveLock); } @@ -370,7 +370,6 @@ RemoveAggregate(char *aggName, char *aggType) Oid basetypeID = InvalidOid; bool defined; - /* * if a basetype is passed in, then attempt to find an aggregate for * that specific type. @@ -405,10 +404,11 @@ RemoveAggregate(char *aggName, char *aggType) } relation = heap_openr(AggregateRelationName, RowExclusiveLock); - tup = SearchSysCacheTuple(AGGNAME, - PointerGetDatum(aggName), - ObjectIdGetDatum(basetypeID), - 0, 0); + + tup = SearchSysCache(AGGNAME, + PointerGetDatum(aggName), + ObjectIdGetDatum(basetypeID), + 0, 0); if (!HeapTupleIsValid(tup)) { @@ -431,5 +431,7 @@ RemoveAggregate(char *aggName, char *aggType) heap_delete(relation, &tup->t_self, NULL); + ReleaseSysCache(tup); + heap_close(relation, RowExclusiveLock); } diff --git a/src/backend/commands/rename.c b/src/backend/commands/rename.c index 6a9de4abf00..3722948047b 100644 --- a/src/backend/commands/rename.c +++ b/src/backend/commands/rename.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.52 2000/11/08 22:09:57 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.53 2000/11/16 22:30:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -58,8 +58,7 @@ renameatt(char *relname, Relation targetrelation; Relation attrelation; HeapTuple reltup, - oldatttup, - newatttup; + atttup; Oid relid; /* @@ -113,9 +112,9 @@ renameatt(char *relname, if (childrelid == relid) continue; - reltup = SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(childrelid), - 0, 0, 0); + reltup = SearchSysCache(RELOID, + ObjectIdGetDatum(childrelid), + 0, 0, 0); if (!HeapTupleIsValid(reltup)) { elog(ERROR, "renameatt: can't find catalog entry for inheriting class with oid %u", @@ -125,6 +124,7 @@ renameatt(char *relname, StrNCpy(childname, NameStr(((Form_pg_class) GETSTRUCT(reltup))->relname), NAMEDATALEN); + ReleaseSysCache(reltup); /* note we need not recurse again! */ renameatt(childname, oldattname, newattname, 0); } @@ -132,42 +132,38 @@ renameatt(char *relname, attrelation = heap_openr(AttributeRelationName, RowExclusiveLock); - oldatttup = SearchSysCacheTupleCopy(ATTNAME, - ObjectIdGetDatum(relid), - PointerGetDatum(oldattname), - 0, 0); - if (!HeapTupleIsValid(oldatttup)) + atttup = SearchSysCacheCopy(ATTNAME, + ObjectIdGetDatum(relid), + PointerGetDatum(oldattname), + 0, 0); + if (!HeapTupleIsValid(atttup)) elog(ERROR, "renameatt: attribute \"%s\" does not exist", oldattname); - if (((Form_pg_attribute) GETSTRUCT(oldatttup))->attnum < 0) + if (((Form_pg_attribute) GETSTRUCT(atttup))->attnum < 0) elog(ERROR, "renameatt: system attribute \"%s\" not renamed", oldattname); - newatttup = SearchSysCacheTuple(ATTNAME, - ObjectIdGetDatum(relid), - PointerGetDatum(newattname), - 0, 0); /* should not already exist */ - if (HeapTupleIsValid(newatttup)) - { - heap_freetuple(oldatttup); + if (SearchSysCacheExists(ATTNAME, + ObjectIdGetDatum(relid), + PointerGetDatum(newattname), + 0, 0)) elog(ERROR, "renameatt: attribute \"%s\" exists", newattname); - } - StrNCpy(NameStr(((Form_pg_attribute) GETSTRUCT(oldatttup))->attname), + StrNCpy(NameStr(((Form_pg_attribute) GETSTRUCT(atttup))->attname), newattname, NAMEDATALEN); - heap_update(attrelation, &oldatttup->t_self, oldatttup, NULL); + heap_update(attrelation, &atttup->t_self, atttup, NULL); /* keep system catalog indices current */ { Relation irelations[Num_pg_attr_indices]; CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, irelations); - CatalogIndexInsert(irelations, Num_pg_attr_indices, attrelation, oldatttup); + CatalogIndexInsert(irelations, Num_pg_attr_indices, attrelation, atttup); CatalogCloseIndices(Num_pg_attr_indices, irelations); } - heap_freetuple(oldatttup); + heap_freetuple(atttup); heap_close(attrelation, RowExclusiveLock); } @@ -179,7 +175,7 @@ renamerel(const char *oldrelname, const char *newrelname) { Relation targetrelation; Relation relrelation; /* for RELATION relation */ - HeapTuple oldreltup; + HeapTuple reltup; Oid reloid; char relkind; Relation irelations[Num_pg_class_indices]; @@ -238,27 +234,27 @@ renamerel(const char *oldrelname, const char *newrelname) */ relrelation = heap_openr(RelationRelationName, RowExclusiveLock); - oldreltup = SearchSysCacheTupleCopy(RELNAME, - PointerGetDatum(oldrelname), - 0, 0, 0); - if (!HeapTupleIsValid(oldreltup)) + reltup = SearchSysCacheCopy(RELNAME, + PointerGetDatum(oldrelname), + 0, 0, 0); + if (!HeapTupleIsValid(reltup)) elog(ERROR, "renamerel: relation \"%s\" does not exist", oldrelname); if (RelnameFindRelid(newrelname) != InvalidOid) elog(ERROR, "renamerel: relation \"%s\" exists", newrelname); /* - * Update pg_class tuple with new relname. (Scribbling on oldreltup + * Update pg_class tuple with new relname. (Scribbling on reltup * is OK because it's a copy...) */ - StrNCpy(NameStr(((Form_pg_class) GETSTRUCT(oldreltup))->relname), + StrNCpy(NameStr(((Form_pg_class) GETSTRUCT(reltup))->relname), newrelname, NAMEDATALEN); - heap_update(relrelation, &oldreltup->t_self, oldreltup, NULL); + heap_update(relrelation, &reltup->t_self, reltup, NULL); /* keep the system catalog indices current */ CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, irelations); - CatalogIndexInsert(irelations, Num_pg_class_indices, relrelation, oldreltup); + CatalogIndexInsert(irelations, Num_pg_class_indices, relrelation, reltup); CatalogCloseIndices(Num_pg_class_indices, irelations); heap_close(relrelation, NoLock); diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 33340291e1c..22dfcac0524 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.79 2000/11/08 22:09:57 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.80 2000/11/16 22:30:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -154,11 +154,11 @@ CreateTrigger(CreateTrigStmt *stmt) * Find and validate the trigger function. */ MemSet(fargtypes, 0, FUNC_MAX_ARGS * sizeof(Oid)); - tuple = SearchSysCacheTuple(PROCNAME, - PointerGetDatum(stmt->funcname), - Int32GetDatum(0), - PointerGetDatum(fargtypes), - 0); + tuple = SearchSysCache(PROCNAME, + PointerGetDatum(stmt->funcname), + Int32GetDatum(0), + PointerGetDatum(fargtypes), + 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "CreateTrigger: function %s() does not exist", stmt->funcname); @@ -167,6 +167,8 @@ CreateTrigger(CreateTrigStmt *stmt) stmt->funcname); funcoid = tuple->t_data->t_oid; funclang = ((Form_pg_proc) GETSTRUCT(tuple))->prolang; + ReleaseSysCache(tuple); + if (funclang != ClanguageId && funclang != NEWClanguageId && funclang != INTERNALlanguageId && @@ -174,14 +176,15 @@ CreateTrigger(CreateTrigStmt *stmt) { HeapTuple langTup; - langTup = SearchSysCacheTuple(LANGOID, - ObjectIdGetDatum(funclang), - 0, 0, 0); + langTup = SearchSysCache(LANGOID, + ObjectIdGetDatum(funclang), + 0, 0, 0); if (!HeapTupleIsValid(langTup)) elog(ERROR, "CreateTrigger: cache lookup for PL %u failed", funclang); if (((Form_pg_language) GETSTRUCT(langTup))->lanispl == false) elog(ERROR, "CreateTrigger: only builtin, C and PL functions are supported"); + ReleaseSysCache(langTup); } /* @@ -268,9 +271,9 @@ CreateTrigger(CreateTrigStmt *stmt) * rebuild relcache entries. */ pgrel = heap_openr(RelationRelationName, RowExclusiveLock); - tuple = SearchSysCacheTupleCopy(RELNAME, - PointerGetDatum(stmt->relname), - 0, 0, 0); + tuple = SearchSysCacheCopy(RELNAME, + PointerGetDatum(stmt->relname), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "CreateTrigger: relation %s not found in pg_class", stmt->relname); @@ -353,9 +356,9 @@ DropTrigger(DropTrigStmt *stmt) * rebuild relcache entries. */ pgrel = heap_openr(RelationRelationName, RowExclusiveLock); - tuple = SearchSysCacheTupleCopy(RELNAME, - PointerGetDatum(stmt->relname), - 0, 0, 0); + tuple = SearchSysCacheCopy(RELNAME, + PointerGetDatum(stmt->relname), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "DropTrigger: relation %s not found in pg_class", stmt->relname); @@ -426,9 +429,9 @@ RelationRemoveTriggers(Relation rel) Relation ridescs[Num_pg_class_indices]; pgrel = heap_openr(RelationRelationName, RowExclusiveLock); - tup = SearchSysCacheTupleCopy(RELOID, - RelationGetRelid(rel), - 0, 0, 0); + tup = SearchSysCacheCopy(RELOID, + RelationGetRelid(rel), + 0, 0, 0); if (!HeapTupleIsValid(tup)) elog(ERROR, "RelationRemoveTriggers: relation %u not found in pg_class", RelationGetRelid(rel)); diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index 55064bf5126..a33098b2e0b 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.69 2000/10/19 03:55:51 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.70 2000/11/16 22:30:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -363,9 +363,9 @@ AlterUser(AlterUserStmt *stmt) pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock); pg_shadow_dsc = RelationGetDescr(pg_shadow_rel); - tuple = SearchSysCacheTuple(SHADOWNAME, - PointerGetDatum(stmt->user), - 0, 0, 0); + tuple = SearchSysCache(SHADOWNAME, + PointerGetDatum(stmt->user), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) { heap_close(pg_shadow_rel, AccessExclusiveLock); @@ -470,10 +470,13 @@ AlterUser(AlterUserStmt *stmt) CatalogOpenIndices(Num_pg_shadow_indices, Name_pg_shadow_indices, idescs); CatalogIndexInsert(idescs, Num_pg_shadow_indices, pg_shadow_rel, - tuple); + new_tuple); CatalogCloseIndices(Num_pg_shadow_indices, idescs); } + ReleaseSysCache(tuple); + heap_freetuple(new_tuple); + /* * Write the updated pg_shadow data to the flat password file. */ @@ -525,9 +528,9 @@ DropUser(DropUserStmt *stmt) int32 usesysid; const char *user = strVal(lfirst(item)); - tuple = SearchSysCacheTuple(SHADOWNAME, - PointerGetDatum(user), - 0, 0, 0); + tuple = SearchSysCache(SHADOWNAME, + PointerGetDatum(user), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) { heap_close(pg_shadow_rel, AccessExclusiveLock); @@ -579,6 +582,8 @@ DropUser(DropUserStmt *stmt) */ heap_delete(pg_shadow_rel, &tuple->t_self, NULL); + ReleaseSysCache(tuple); + /* * Remove user from groups * @@ -633,24 +638,21 @@ CheckPgUserAclNotNull() { HeapTuple htup; - htup = SearchSysCacheTuple(RELNAME, - PointerGetDatum(ShadowRelationName), - 0, 0, 0); + htup = SearchSysCache(RELNAME, + PointerGetDatum(ShadowRelationName), + 0, 0, 0); if (!HeapTupleIsValid(htup)) - { - /* BIG problem */ - elog(ERROR, "IsPgUserAclNull: \"%s\" not found", + elog(ERROR, "CheckPgUserAclNotNull: \"%s\" not found", ShadowRelationName); - } if (heap_attisnull(htup, Anum_pg_class_relacl)) - { elog(ERROR, "To use passwords, you have to revoke permissions on %s " "so normal users cannot read the passwords. " "Try 'REVOKE ALL ON \"%s\" FROM PUBLIC'.", ShadowRelationName, ShadowRelationName); - } + + ReleaseSysCache(htup); } @@ -716,24 +718,21 @@ CreateGroup(CreateGroupStmt *stmt) /* * Translate the given user names to ids */ - foreach(item, stmt->initUsers) { const char *groupuser = strVal(lfirst(item)); Value *v; - tuple = SearchSysCacheTuple(SHADOWNAME, - PointerGetDatum(groupuser), - 0, 0, 0); + tuple = SearchSysCache(SHADOWNAME, + PointerGetDatum(groupuser), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) - { - heap_close(pg_group_rel, AccessExclusiveLock); elog(ERROR, "CREATE GROUP: user \"%s\" does not exist", groupuser); - } v = makeInteger(((Form_pg_shadow) GETSTRUCT(tuple))->usesysid); if (!member(v, newlist)) newlist = lcons(v, newlist); + ReleaseSysCache(tuple); } /* build an array to insert */ @@ -817,20 +816,19 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag) pg_group_dsc = RelationGetDescr(pg_group_rel); /* - * Verify that group exists. If we find a tuple, will take that the - * rest of the way and make our modifications on it. + * Fetch existing tuple for group. */ - if (!HeapTupleIsValid(group_tuple = SearchSysCacheTupleCopy(GRONAME, PointerGetDatum(stmt->name), 0, 0, 0))) - { - heap_close(pg_group_rel, AccessExclusiveLock); + group_tuple = SearchSysCache(GRONAME, + PointerGetDatum(stmt->name), + 0, 0, 0); + if (!HeapTupleIsValid(group_tuple)) elog(ERROR, "%s: group \"%s\" does not exist", tag, stmt->name); - } - - AssertState(stmt->action == +1 || stmt->action == -1); /* * Now decide what to do. */ + AssertState(stmt->action == +1 || stmt->action == -1); + if (stmt->action == +1) /* add users, might also be invoked by * create user */ { @@ -876,15 +874,14 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag) if (strcmp(tag, "ALTER GROUP") == 0) { /* Get the uid of the proposed user to add. */ - tuple = SearchSysCacheTuple(SHADOWNAME, - PointerGetDatum(strVal(lfirst(item))), - 0, 0, 0); + tuple = SearchSysCache(SHADOWNAME, + PointerGetDatum(strVal(lfirst(item))), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) - { - heap_close(pg_group_rel, AccessExclusiveLock); - elog(ERROR, "%s: user \"%s\" does not exist", tag, strVal(lfirst(item))); - } + elog(ERROR, "%s: user \"%s\" does not exist", + tag, strVal(lfirst(item))); v = makeInteger(((Form_pg_shadow) GETSTRUCT(tuple))->usesysid); + ReleaseSysCache(tuple); } else if (strcmp(tag, "CREATE USER") == 0) { @@ -999,15 +996,13 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag) if (!is_dropuser) { /* Get the uid of the proposed user to drop. */ - tuple = SearchSysCacheTuple(SHADOWNAME, - PointerGetDatum(strVal(lfirst(item))), - 0, 0, 0); + tuple = SearchSysCache(SHADOWNAME, + PointerGetDatum(strVal(lfirst(item))), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) - { - heap_close(pg_group_rel, AccessExclusiveLock); elog(ERROR, "ALTER GROUP: user \"%s\" does not exist", strVal(lfirst(item))); - } v = makeInteger(((Form_pg_shadow) GETSTRUCT(tuple))->usesysid); + ReleaseSysCache(tuple); } else { @@ -1056,9 +1051,9 @@ AlterGroup(AlterGroupStmt *stmt, const char *tag) } /* endif group not null */ } /* endif alter group drop user */ - heap_close(pg_group_rel, AccessExclusiveLock); + ReleaseSysCache(group_tuple); - pfree(group_tuple); + heap_close(pg_group_rel, AccessExclusiveLock); } diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 403d80942de..3aeae1409bd 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.172 2000/11/16 05:50:59 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.173 2000/11/16 22:30:19 tgl Exp $ * *------------------------------------------------------------------------- @@ -356,7 +356,6 @@ getrels(NameData *VacRelP) static void vacuum_rel(Oid relid, bool analyze, bool is_toastrel) { - HeapTuple tuple; Relation onerel; VacPageListData vacuum_pages; /* List of pages to vacuum and/or clean * indices */ @@ -384,10 +383,9 @@ vacuum_rel(Oid relid, bool analyze, bool is_toastrel) * Race condition -- if the pg_class tuple has gone away since the * last time we saw it, we don't need to vacuum it. */ - tuple = SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(relid), - 0, 0, 0); - if (!HeapTupleIsValid(tuple)) + if (!SearchSysCacheExists(RELOID, + ObjectIdGetDatum(relid), + 0, 0, 0)) { if (!is_toastrel) CommitTransactionCommand(); @@ -2237,17 +2235,17 @@ update_relstats(Oid relid, int num_pages, int num_tuples, bool hasindex, */ rd = heap_openr(RelationRelationName, RowExclusiveLock); - ctup = SearchSysCacheTupleCopy(RELOID, - ObjectIdGetDatum(relid), - 0, 0, 0); + ctup = SearchSysCache(RELOID, + ObjectIdGetDatum(relid), + 0, 0, 0); if (!HeapTupleIsValid(ctup)) elog(ERROR, "pg_class entry for relid %u vanished during vacuuming", relid); /* get the buffer cache tuple */ rtup.t_self = ctup->t_self; + ReleaseSysCache(ctup); heap_fetch(rd, SnapshotNow, &rtup, &buffer); - heap_freetuple(ctup); /* overwrite the existing statistics in the tuple */ pgcform = (Form_pg_class) GETSTRUCT(&rtup); @@ -2481,13 +2479,14 @@ get_index_desc(Relation onerel, int nindices, Relation *Irel) for (i = 0; i < nindices; i++) { - cachetuple = SearchSysCacheTuple(INDEXRELID, + cachetuple = SearchSysCache(INDEXRELID, ObjectIdGetDatum(RelationGetRelid(Irel[i])), - 0, 0, 0); + 0, 0, 0); if (!HeapTupleIsValid(cachetuple)) elog(ERROR, "get_index_desc: index %u not found", RelationGetRelid(Irel[i])); indexInfo[i] = BuildIndexInfo(cachetuple); + ReleaseSysCache(cachetuple); } return indexInfo; diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index ecdda594188..3b05a78e83a 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.68 2000/11/12 00:36:57 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.69 2000/11/16 22:30:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -740,9 +740,9 @@ ExecOpenIndices(ResultRelInfo *resultRelInfo) * Get the pg_index tuple for the index * ---------------- */ - indexTuple = SearchSysCacheTuple(INDEXRELID, - ObjectIdGetDatum(indexOid), - 0, 0, 0); + indexTuple = SearchSysCache(INDEXRELID, + ObjectIdGetDatum(indexOid), + 0, 0, 0); if (!HeapTupleIsValid(indexTuple)) elog(ERROR, "ExecOpenIndices: index %u not found", indexOid); @@ -752,6 +752,8 @@ ExecOpenIndices(ResultRelInfo *resultRelInfo) */ ii = BuildIndexInfo(indexTuple); + ReleaseSysCache(indexTuple); + relationDescs[i] = indexDesc; indexInfoArray[i] = ii; i++; diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index ca9c48e294d..98b28c61e10 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.40 2000/11/12 00:36:57 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.41 2000/11/16 22:30:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -183,14 +183,11 @@ init_sql_fcache(FmgrInfo *finfo) /* ---------------- * get the procedure tuple corresponding to the given function Oid - * - * NB: use SearchSysCacheTupleCopy to ensure tuple lives long enough * ---------------- */ - procedureTuple = SearchSysCacheTupleCopy(PROCOID, - ObjectIdGetDatum(foid), - 0, 0, 0); - + procedureTuple = SearchSysCache(PROCOID, + ObjectIdGetDatum(foid), + 0, 0, 0); if (!HeapTupleIsValid(procedureTuple)) elog(ERROR, "init_sql_fcache: Cache lookup failed for procedure %u", foid); @@ -201,10 +198,9 @@ init_sql_fcache(FmgrInfo *finfo) * get the return type from the procedure tuple * ---------------- */ - typeTuple = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(procedureStruct->prorettype), - 0, 0, 0); - + typeTuple = SearchSysCache(TYPEOID, + ObjectIdGetDatum(procedureStruct->prorettype), + 0, 0, 0); if (!HeapTupleIsValid(typeTuple)) elog(ERROR, "init_sql_fcache: Cache lookup failed for type %u", procedureStruct->prorettype); @@ -286,7 +282,8 @@ init_sql_fcache(FmgrInfo *finfo) pfree(src); - heap_freetuple(procedureTuple); + ReleaseSysCache(typeTuple); + ReleaseSysCache(procedureTuple); finfo->fn_extra = (void *) fcache; } diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index fae1a5b0d87..827001384f6 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -34,7 +34,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.71 2000/08/24 03:29:03 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.72 2000/11/16 22:30:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -51,6 +51,7 @@ #include "parser/parse_expr.h" #include "parser/parse_oper.h" #include "parser/parse_type.h" +#include "utils/lsyscache.h" #include "utils/syscache.h" #include "utils/tuplesort.h" #include "utils/datum.h" @@ -105,7 +106,7 @@ typedef struct AggStatePerAggData * We need the len and byval info for the agg's input, result, and * transition data types in order to know how to copy/delete values. */ - int inputtypeLen, + int16 inputtypeLen, resulttypeLen, transtypeLen; bool inputtypeByVal, @@ -827,7 +828,6 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent) char *aggname = aggref->aggname; HeapTuple aggTuple; Form_pg_aggregate aggform; - Type typeInfo; Oid transfn_oid, finalfn_oid; @@ -837,23 +837,23 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent) /* Fill in the peraggstate data */ peraggstate->aggref = aggref; - aggTuple = SearchSysCacheTupleCopy(AGGNAME, - PointerGetDatum(aggname), - ObjectIdGetDatum(aggref->basetype), - 0, 0); + aggTuple = SearchSysCache(AGGNAME, + PointerGetDatum(aggname), + ObjectIdGetDatum(aggref->basetype), + 0, 0); if (!HeapTupleIsValid(aggTuple)) elog(ERROR, "ExecAgg: cache lookup failed for aggregate %s(%s)", aggname, - typeidTypeName(aggref->basetype)); + aggref->basetype ? + typeidTypeName(aggref->basetype) : (char *) ""); aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple); - typeInfo = typeidType(aggform->aggfinaltype); - peraggstate->resulttypeLen = typeLen(typeInfo); - peraggstate->resulttypeByVal = typeByVal(typeInfo); - - typeInfo = typeidType(aggform->aggtranstype); - peraggstate->transtypeLen = typeLen(typeInfo); - peraggstate->transtypeByVal = typeByVal(typeInfo); + get_typlenbyval(aggform->aggfinaltype, + &peraggstate->resulttypeLen, + &peraggstate->resulttypeByVal); + get_typlenbyval(aggform->aggtranstype, + &peraggstate->transtypeLen, + &peraggstate->transtypeByVal); peraggstate->initValue = AggNameGetInitVal(aggname, @@ -901,23 +901,22 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent) Form_pg_operator pgopform; peraggstate->inputType = inputType; - typeInfo = typeidType(inputType); - peraggstate->inputtypeLen = typeLen(typeInfo); - peraggstate->inputtypeByVal = typeByVal(typeInfo); + get_typlenbyval(inputType, + &peraggstate->inputtypeLen, + &peraggstate->inputtypeByVal); eq_operator = oper("=", inputType, inputType, true); if (!HeapTupleIsValid(eq_operator)) - { elog(ERROR, "Unable to identify an equality operator for type '%s'", typeidTypeName(inputType)); - } pgopform = (Form_pg_operator) GETSTRUCT(eq_operator); fmgr_info(pgopform->oprcode, &(peraggstate->equalfn)); + ReleaseSysCache(eq_operator); peraggstate->sortOperator = any_ordering_op(inputType); peraggstate->sortstate = NULL; } - heap_freetuple(aggTuple); + ReleaseSysCache(aggTuple); } return TRUE; diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c index 8fc319a77f0..88b4cd27335 100644 --- a/src/backend/executor/nodeGroup.c +++ b/src/backend/executor/nodeGroup.c @@ -15,7 +15,7 @@ * locate group boundaries. * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.38 2000/08/24 03:29:03 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.39 2000/11/16 22:30:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -28,6 +28,8 @@ #include "executor/nodeGroup.h" #include "parser/parse_oper.h" #include "parser/parse_type.h" +#include "utils/lsyscache.h" +#include "utils/syscache.h" static TupleTableSlot *ExecGroupEveryTuple(Group *node); static TupleTableSlot *ExecGroupOneTuple(Group *node); @@ -498,12 +500,11 @@ execTuplesMatchPrepare(TupleDesc tupdesc, eq_operator = oper("=", typid, typid, true); if (!HeapTupleIsValid(eq_operator)) - { elog(ERROR, "Unable to identify an equality operator for type '%s'", typeidTypeName(typid)); - } pgopform = (Form_pg_operator) GETSTRUCT(eq_operator); fmgr_info(pgopform->oprcode, &eqfunctions[i]); + ReleaseSysCache(eq_operator); } return eqfunctions; diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c index 9cd85195cdc..1969c5f0bd6 100644 --- a/src/backend/executor/nodeHash.c +++ b/src/backend/executor/nodeHash.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * - * $Id: nodeHash.c,v 1.52 2000/08/24 03:29:03 tgl Exp $ + * $Id: nodeHash.c,v 1.53 2000/11/16 22:30:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -29,8 +29,8 @@ #include "executor/nodeHashjoin.h" #include "miscadmin.h" #include "parser/parse_expr.h" -#include "parser/parse_type.h" #include "utils/memutils.h" +#include "utils/lsyscache.h" static int hashFunc(Datum key, int len, bool byVal); @@ -237,7 +237,6 @@ ExecHashTableCreate(Hash *node) int totalbuckets; int bucketsize; int i; - Type typeInfo; MemoryContext oldcxt; /* ---------------- @@ -353,9 +352,9 @@ ExecHashTableCreate(Hash *node) * Get info about the datatype of the hash key. * ---------------- */ - typeInfo = typeidType(exprType(node->hashkey)); - hashtable->typByVal = typeByVal(typeInfo); - hashtable->typLen = typeLen(typeInfo); + get_typlenbyval(exprType(node->hashkey), + &hashtable->typLen, + &hashtable->typByVal); /* ---------------- * Create temporary memory contexts in which to keep the hashtable @@ -546,7 +545,9 @@ ExecHashGetBucket(HashJoinTable hashtable, } else { - bucketno = hashFunc(keyval, hashtable->typLen, hashtable->typByVal) + bucketno = hashFunc(keyval, + (int) hashtable->typLen, + hashtable->typByVal) % hashtable->totalbuckets; } diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c index 9d4ca0a8d54..dbeaa7a2a53 100644 --- a/src/backend/executor/nodeMergejoin.c +++ b/src/backend/executor/nodeMergejoin.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.38 2000/09/12 21:06:48 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.39 2000/11/16 22:30:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -147,26 +147,29 @@ MJFormSkipQual(List *qualList, char *replaceopname) * if we search with the actual operand types. * ---------------- */ - optup = get_operator_tuple(op->opno); + optup = SearchSysCache(OPEROID, + ObjectIdGetDatum(op->opno), + 0, 0, 0); if (!HeapTupleIsValid(optup)) /* shouldn't happen */ elog(ERROR, "MJFormSkipQual: operator %u not found", op->opno); opform = (Form_pg_operator) GETSTRUCT(optup); oprleft = opform->oprleft; oprright = opform->oprright; + ReleaseSysCache(optup); /* ---------------- * Now look up the matching "<" or ">" operator. If there isn't one, * whoever marked the "=" operator mergejoinable was a loser. * ---------------- */ - optup = SearchSysCacheTuple(OPERNAME, - PointerGetDatum(replaceopname), - ObjectIdGetDatum(oprleft), - ObjectIdGetDatum(oprright), - CharGetDatum('b')); + optup = SearchSysCache(OPERNAME, + PointerGetDatum(replaceopname), + ObjectIdGetDatum(oprleft), + ObjectIdGetDatum(oprright), + CharGetDatum('b')); if (!HeapTupleIsValid(optup)) elog(ERROR, - "MJFormSkipQual: mergejoin operator %u has no matching %s op", + "MJFormSkipQual: mergejoin operator %u has no matching %s op", op->opno, replaceopname); opform = (Form_pg_operator) GETSTRUCT(optup); @@ -177,6 +180,7 @@ MJFormSkipQual(List *qualList, char *replaceopname) op->opno = optup->t_data->t_oid; op->opid = opform->oprcode; op->op_fcache = NULL; + ReleaseSysCache(optup); } return qualCopy; diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index 07a05561a64..74a5dc44415 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -3,7 +3,7 @@ * spi.c * Server Programming Interface * - * $Id: spi.c,v 1.48 2000/10/26 21:35:15 tgl Exp $ + * $Id: spi.c,v 1.49 2000/11/16 22:30:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -447,6 +447,7 @@ char * SPI_gettype(TupleDesc tupdesc, int fnumber) { HeapTuple typeTuple; + char *result; SPI_result = 0; if (tupdesc->natts < fnumber || fnumber <= 0) @@ -455,9 +456,9 @@ SPI_gettype(TupleDesc tupdesc, int fnumber) return NULL; } - typeTuple = SearchSysCacheTuple(TYPEOID, + typeTuple = SearchSysCache(TYPEOID, ObjectIdGetDatum(tupdesc->attrs[fnumber - 1]->atttypid), - 0, 0, 0); + 0, 0, 0); if (!HeapTupleIsValid(typeTuple)) { @@ -465,7 +466,9 @@ SPI_gettype(TupleDesc tupdesc, int fnumber) return NULL; } - return pstrdup(NameStr(((Form_pg_type) GETSTRUCT(typeTuple))->typname)); + result = pstrdup(NameStr(((Form_pg_type) GETSTRUCT(typeTuple))->typname)); + ReleaseSysCache(typeTuple); + return result; } Oid diff --git a/src/backend/lib/dllist.c b/src/backend/lib/dllist.c index f38251934c4..175c02c3e7c 100644 --- a/src/backend/lib/dllist.c +++ b/src/backend/lib/dllist.c @@ -2,7 +2,6 @@ * * dllist.c * this is a simple doubly linked list implementation - * replaces the old simplelists stuff * the elements of the lists are void* * * Portions Copyright (c) 1996-2000, PostgreSQL, Inc @@ -10,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/lib/dllist.c,v 1.18 2000/06/08 22:37:05 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/lib/dllist.c,v 1.19 2000/11/16 22:30:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -33,25 +32,33 @@ DLNewList(void) { Dllist *l; - l = malloc(sizeof(Dllist)); + l = (Dllist *) malloc(sizeof(Dllist)); l->dll_head = 0; l->dll_tail = 0; return l; } -/* free up a list and all the nodes in it --- but *not* whatever the nodes +void +DLInitList(Dllist *list) +{ + list->dll_head = 0; + list->dll_tail = 0; +} + +/* + * free up a list and all the nodes in it --- but *not* whatever the nodes * might point to! */ void -DLFreeList(Dllist *l) +DLFreeList(Dllist *list) { Dlelem *curr; - while ((curr = DLRemHead(l)) != 0) + while ((curr = DLRemHead(list)) != 0) free(curr); - free(l); + free(list); } Dlelem * @@ -59,7 +66,7 @@ DLNewElem(void *val) { Dlelem *e; - e = malloc(sizeof(Dlelem)); + e = (Dlelem *) malloc(sizeof(Dlelem)); e->dle_next = 0; e->dle_prev = 0; e->dle_val = val; @@ -68,59 +75,18 @@ DLNewElem(void *val) } void -DLFreeElem(Dlelem *e) -{ - free(e); -} - -Dlelem * -DLGetHead(Dllist *l) -{ - return l ? l->dll_head : 0; -} - -/* get the value stored in the first element */ -#ifdef NOT_USED -void * -DLGetHeadVal(Dllist *l) +DLInitElem(Dlelem *e, void *val) { - Dlelem *e = DLGetHead(l); - - return e ? e->dle_val : 0; -} - -#endif - -Dlelem * -DLGetTail(Dllist *l) -{ - return l ? l->dll_tail : 0; -} - -/* get the value stored in the last element */ -#ifdef NOT_USED -void * -DLGetTailVal(Dllist *l) -{ - Dlelem *e = DLGetTail(l); - - return e ? e->dle_val : 0; -} - -#endif - -#ifdef NOT_USED -Dlelem * -DLGetPred(Dlelem *e) /* get predecessor */ -{ - return e ? e->dle_prev : 0; + e->dle_next = 0; + e->dle_prev = 0; + e->dle_val = val; + e->dle_list = 0; } -#endif -Dlelem * -DLGetSucc(Dlelem *e) /* get successor */ +void +DLFreeElem(Dlelem *e) { - return e ? e->dle_next : 0; + free(e); } void @@ -131,16 +97,16 @@ DLRemove(Dlelem *e) if (e->dle_prev) e->dle_prev->dle_next = e->dle_next; else -/* must be the head element */ { + /* must be the head element */ Assert(e == l->dll_head); l->dll_head = e->dle_next; } if (e->dle_next) e->dle_next->dle_prev = e->dle_prev; else -/* must be the tail element */ { + /* must be the tail element */ Assert(e == l->dll_tail); l->dll_tail = e->dle_prev; } @@ -194,12 +160,12 @@ DLRemHead(Dllist *l) l->dll_head = result->dle_next; - result->dle_next = 0; - result->dle_list = 0; - if (result == l->dll_tail) /* if the head is also the tail */ l->dll_tail = 0; + result->dle_next = 0; + result->dle_list = 0; + return result; } @@ -217,12 +183,12 @@ DLRemTail(Dllist *l) l->dll_tail = result->dle_prev; - result->dle_prev = 0; - result->dle_list = 0; - if (result == l->dll_head) /* if the tail is also the head */ l->dll_head = 0; + result->dle_prev = 0; + result->dle_list = 0; + return result; } @@ -241,8 +207,8 @@ DLMoveToFront(Dlelem *e) if (e->dle_next) e->dle_next->dle_prev = e->dle_prev; else -/* must be the tail element */ { + /* must be the tail element */ Assert(e == l->dll_tail); l->dll_tail = e->dle_prev; } diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c index 45e1c03738c..95bf730963f 100644 --- a/src/backend/nodes/makefuncs.c +++ b/src/backend/nodes/makefuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.22 2000/08/08 15:41:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.23 2000/11/16 22:30:23 tgl Exp $ * * NOTES * Creator functions in POSTGRES 4.2 are generated automatically. Most of @@ -20,7 +20,10 @@ * Andrew Yu Oct 20, 1994 file creation */ #include "postgres.h" + #include "nodes/makefuncs.h" +#include "utils/lsyscache.h" + /* * makeOper - @@ -144,6 +147,26 @@ makeConst(Oid consttype, } /* + * makeNullConst - + * creates a Const node representing a NULL of the specified type + */ +Const * +makeNullConst(Oid consttype) +{ + int16 typLen; + bool typByVal; + + get_typlenbyval(consttype, &typLen, &typByVal); + return makeConst(consttype, + (int) typLen, + (Datum) 0, + true, + typByVal, + false, + false); +} + +/* * makeAttr - * creates an Attr node */ diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index db318a1b312..7abca0990e6 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.133 2000/11/16 05:51:00 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.134 2000/11/16 22:30:23 tgl Exp $ * * NOTES * Every (plan) node in POSTGRES has an associated "out" routine which @@ -1236,8 +1236,8 @@ _outJoinInfo(StringInfo str, JoinInfo *node) static void _outDatum(StringInfo str, Datum value, Oid type) { + int16 typeLength; bool byValue; - int typeLength; Size length; char *s; int i; @@ -1246,8 +1246,7 @@ _outDatum(StringInfo str, Datum value, Oid type) * find some information about the type and the "real" length of the * datum. */ - byValue = get_typbyval(type); - typeLength = get_typlen(type); + get_typlenbyval(type, &typeLength, &byValue); length = datumGetSize(value, byValue, typeLength); if (byValue) diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 5ed42accdb0..43577f94f99 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.97 2000/09/29 18:21:32 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.98 2000/11/16 22:30:24 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -808,9 +808,9 @@ indexable_operator(Expr *clause, Oid opclass, Oid relam, bool indexkey_on_left) { Oid expr_op = ((Oper *) clause->oper)->opno; - Oid commuted_op; - Operator oldop, - newop; + Oid commuted_op, + new_op; + Operator oldoptup; Form_pg_operator oldopform; char *opname; Oid ltype, @@ -835,13 +835,16 @@ indexable_operator(Expr *clause, Oid opclass, Oid relam, * Get the nominal input types of the given operator and the actual * type (before binary-compatible relabeling) of the index key. */ - oldop = get_operator_tuple(expr_op); - if (! HeapTupleIsValid(oldop)) + oldoptup = SearchSysCache(OPEROID, + ObjectIdGetDatum(expr_op), + 0, 0, 0); + if (! HeapTupleIsValid(oldoptup)) return InvalidOid; /* probably can't happen */ - oldopform = (Form_pg_operator) GETSTRUCT(oldop); - opname = NameStr(oldopform->oprname); + oldopform = (Form_pg_operator) GETSTRUCT(oldoptup); + opname = pstrdup(NameStr(oldopform->oprname)); ltype = oldopform->oprleft; rtype = oldopform->oprright; + ReleaseSysCache(oldoptup); if (indexkey_on_left) { @@ -875,13 +878,11 @@ indexable_operator(Expr *clause, Oid opclass, Oid relam, * (In theory this might find a non-semantically-comparable operator, * but in practice that seems pretty unlikely for binary-compatible types.) */ - newop = oper(opname, indexkeytype, indexkeytype, TRUE); + new_op = oper_oid(opname, indexkeytype, indexkeytype, true); - if (HeapTupleIsValid(newop)) + if (OidIsValid(new_op)) { - Oid new_expr_op = oprid(newop); - - if (new_expr_op != expr_op) + if (new_op != expr_op) { /* @@ -889,14 +890,14 @@ indexable_operator(Expr *clause, Oid opclass, Oid relam, * name; now does it match the index? */ if (indexkey_on_left) - commuted_op = new_expr_op; + commuted_op = new_op; else - commuted_op = get_commutator(new_expr_op); + commuted_op = get_commutator(new_op); if (commuted_op == InvalidOid) return InvalidOid; if (op_class(commuted_op, opclass, relam)) - return new_expr_op; + return new_op; } } @@ -2079,16 +2080,11 @@ prefix_quals(Var *leftop, Oid expr_op, static Oid find_operator(const char *opname, Oid datatype) { - HeapTuple optup; - - optup = SearchSysCacheTuple(OPERNAME, - PointerGetDatum(opname), - ObjectIdGetDatum(datatype), - ObjectIdGetDatum(datatype), - CharGetDatum('b')); - if (!HeapTupleIsValid(optup)) - return InvalidOid; - return optup->t_data->t_oid; + return GetSysCacheOid(OPERNAME, + PointerGetDatum(opname), + ObjectIdGetDatum(datatype), + ObjectIdGetDatum(datatype), + CharGetDatum('b')); } /* diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 4069ed66e58..bfb97bc1eb5 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.100 2000/11/12 00:36:58 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.101 2000/11/16 22:30:24 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -396,17 +396,19 @@ create_indexscan_plan(Query *root, HeapTuple indexTuple; Form_pg_index index; - indexTuple = SearchSysCacheTuple(INDEXRELID, - ObjectIdGetDatum(lfirsti(ixid)), - 0, 0, 0); + indexTuple = SearchSysCache(INDEXRELID, + ObjectIdGetDatum(lfirsti(ixid)), + 0, 0, 0); if (!HeapTupleIsValid(indexTuple)) elog(ERROR, "create_plan: index %u not found", lfirsti(ixid)); index = (Form_pg_index) GETSTRUCT(indexTuple); if (index->indislossy) { lossy = true; + ReleaseSysCache(indexTuple); break; } + ReleaseSysCache(indexTuple); } /* @@ -904,18 +906,19 @@ fix_indxqual_references(List *indexquals, IndexPath *index_path) Form_pg_index index; /* Get the relam from the index's pg_class entry */ - indexTuple = SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(indexid), - 0, 0, 0); + indexTuple = SearchSysCache(RELOID, + ObjectIdGetDatum(indexid), + 0, 0, 0); if (!HeapTupleIsValid(indexTuple)) elog(ERROR, "fix_indxqual_references: index %u not found in pg_class", indexid); relam = ((Form_pg_class) GETSTRUCT(indexTuple))->relam; + ReleaseSysCache(indexTuple); /* Need the index's pg_index entry for other stuff */ - indexTuple = SearchSysCacheTuple(INDEXRELID, - ObjectIdGetDatum(indexid), - 0, 0, 0); + indexTuple = SearchSysCache(INDEXRELID, + ObjectIdGetDatum(indexid), + 0, 0, 0); if (!HeapTupleIsValid(indexTuple)) elog(ERROR, "fix_indxqual_references: index %u not found in pg_index", indexid); @@ -927,6 +930,8 @@ fix_indxqual_references(List *indexquals, IndexPath *index_path) relam, index)); + ReleaseSysCache(indexTuple); + indexids = lnext(indexids); } return fixed_quals; diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index acee58b7f07..3bea06e2af6 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.51 2000/09/29 18:21:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.52 2000/11/16 22:30:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -31,6 +31,7 @@ #include "parser/parse_oper.h" #include "parser/parse_type.h" #include "utils/lsyscache.h" +#include "utils/syscache.h" static void mark_baserels_for_outer_join(Query *root, Relids rels, @@ -636,6 +637,8 @@ process_implied_equality(Query *root, Node *item1, Node *item2, BOOLOID); /* operator result type */ clause->args = makeList2(item1, item2); + ReleaseSysCache(eq_operator); + /* * Note: we mark the qual "pushed down" to ensure that it can never be * taken for an original JOIN/ON clause. We also claim it is an outer- diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 296164acb89..c36e7fe7b81 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.44 2000/10/26 21:36:09 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.45 2000/11/16 22:30:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -23,7 +23,7 @@ #include "optimizer/subselect.h" #include "parser/parse_expr.h" #include "parser/parse_oper.h" -#include "utils/lsyscache.h" +#include "utils/syscache.h" Index PlannerQueryLevel; /* level of current query */ @@ -271,8 +271,11 @@ make_subplan(SubLink *slink) pfree(var); /* var is only needed for new_param */ Assert(IsA(oper, Oper)); - tup = get_operator_tuple(oper->opno); - Assert(HeapTupleIsValid(tup)); + tup = SearchSysCache(OPEROID, + ObjectIdGetDatum(oper->opno), + 0, 0, 0); + if (! HeapTupleIsValid(tup)) + elog(ERROR, "cache lookup failed for operator %u", oper->opno); opform = (Form_pg_operator) GETSTRUCT(tup); /* @@ -283,6 +286,8 @@ make_subplan(SubLink *slink) exprType(lefthand), opform->oprleft); right = make_operand("", (Node *) prm, prm->paramtype, opform->oprright); + ReleaseSysCache(tup); + newoper = lappend(newoper, make_opclause(oper, (Var *) left, @@ -401,15 +406,14 @@ make_subplan(SubLink *slink) Node *left, *right; - /* - * XXX really ought to fill in constlen and constbyval - * correctly, but right now ExecEvalExpr won't look at them... - */ - con = makeConst(te->resdom->restype, 0, 0, true, 0, 0, 0); + con = makeNullConst(te->resdom->restype); Assert(IsA(oper, Oper)); - tup = get_operator_tuple(oper->opno); - Assert(HeapTupleIsValid(tup)); + tup = SearchSysCache(OPEROID, + ObjectIdGetDatum(oper->opno), + 0, 0, 0); + if (! HeapTupleIsValid(tup)) + elog(ERROR, "cache lookup failed for operator %u", oper->opno); opform = (Form_pg_operator) GETSTRUCT(tup); /* @@ -420,6 +424,8 @@ make_subplan(SubLink *slink) exprType(lefthand), opform->oprleft); right = make_operand("", (Node *) con, con->consttype, opform->oprright); + ReleaseSysCache(tup); + newoper = lappend(newoper, make_opclause(oper, (Var *) left, diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c index 822c0c79f05..658c6c5e312 100644 --- a/src/backend/optimizer/prep/preptlist.c +++ b/src/backend/optimizer/prep/preptlist.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.39 2000/10/05 19:11:30 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.40 2000/11/16 22:30:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -238,14 +238,7 @@ expand_targetlist(List *tlist, int command_type, #ifdef _DROP_COLUMN_HACK__ if (COLUMN_IS_DROPPED(att_tup)) - { - temp_var = (Var *) makeConst(atttype, 0, - PointerGetDatum(NULL), - true, - false, - false, /* not a set */ - false); - } + temp_var = (Var *) makeNullConst(atttype); else #endif /* _DROP_COLUMN_HACK__ */ temp_var = makeVar(result_relation, diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index f52ec6d2d87..c8df8b26fe4 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.77 2000/10/05 19:11:32 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.78 2000/11/16 22:30:26 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -28,7 +28,6 @@ #include "optimizer/clauses.h" #include "optimizer/tlist.h" #include "optimizer/var.h" -#include "parser/parse_type.h" #include "parser/parsetree.h" #include "utils/datum.h" #include "utils/lsyscache.h" @@ -995,7 +994,8 @@ get_rels_atts(Node *clause, void CommuteClause(Expr *clause) { - HeapTuple heapTup; + Oid opoid; + HeapTuple optup; Form_pg_operator commuTup; Oper *commu; Node *temp; @@ -1004,19 +1004,22 @@ CommuteClause(Expr *clause) length(clause->args) != 2) elog(ERROR, "CommuteClause: applied to non-binary-operator clause"); - heapTup = (HeapTuple) - get_operator_tuple(get_commutator(((Oper *) clause->oper)->opno)); + opoid = ((Oper *) clause->oper)->opno; - if (heapTup == (HeapTuple) NULL) - elog(ERROR, "CommuteClause: no commutator for operator %u", - ((Oper *) clause->oper)->opno); + optup = SearchSysCache(OPEROID, + ObjectIdGetDatum(get_commutator(opoid)), + 0, 0, 0); + if (!HeapTupleIsValid(optup)) + elog(ERROR, "CommuteClause: no commutator for operator %u", opoid); - commuTup = (Form_pg_operator) GETSTRUCT(heapTup); + commuTup = (Form_pg_operator) GETSTRUCT(optup); - commu = makeOper(heapTup->t_data->t_oid, + commu = makeOper(optup->t_data->t_oid, commuTup->oprcode, commuTup->oprresult); + ReleaseSysCache(optup); + /* * re-form the clause in-place! */ @@ -1434,9 +1437,11 @@ simplify_op_or_func(Expr *expr, List *args) Oid result_typeid; HeapTuple func_tuple; Form_pg_proc funcform; - Type resultType; + bool proiscachable; + bool proisstrict; + bool proretset; + int16 resultTypLen; bool resultTypByVal; - int resultTypLen; Expr *newexpr; ExprContext *econtext; Datum const_val; @@ -1491,36 +1496,37 @@ simplify_op_or_func(Expr *expr, List *args) * we could use func_iscachable() here, but we need several fields * out of the func tuple, so might as well just look it up once. */ - func_tuple = SearchSysCacheTuple(PROCOID, - ObjectIdGetDatum(funcid), - 0, 0, 0); + func_tuple = SearchSysCache(PROCOID, + ObjectIdGetDatum(funcid), + 0, 0, 0); if (!HeapTupleIsValid(func_tuple)) elog(ERROR, "Function OID %u does not exist", funcid); funcform = (Form_pg_proc) GETSTRUCT(func_tuple); - if (!funcform->proiscachable) + proiscachable = funcform->proiscachable; + proisstrict = funcform->proisstrict; + proretset = funcform->proretset; + ReleaseSysCache(func_tuple); + + if (!proiscachable) return NULL; /* * Also check to make sure it doesn't return a set. */ - if (funcform->proretset) + if (proretset) return NULL; /* * Now that we know if the function is strict, we can finish the * checks for simplifiable inputs that we started above. */ - if (funcform->proisstrict && has_null_input) + if (proisstrict && has_null_input) { /* * It's strict and has NULL input, so must produce NULL output. * Return a NULL constant of the right type. */ - resultType = typeidType(result_typeid); - return (Expr *) makeConst(result_typeid, typeLen(resultType), - (Datum) 0, true, - typeByVal(resultType), - false, false); + return (Expr *) makeNullConst(result_typeid); } /* @@ -1548,9 +1554,7 @@ simplify_op_or_func(Expr *expr, List *args) newexpr->args = args; /* Get info needed about result datatype */ - resultType = typeidType(result_typeid); - resultTypByVal = typeByVal(resultType); - resultTypLen = typeLen(resultType); + get_typlenbyval(result_typeid, &resultTypLen, &resultTypByVal); /* * It is OK to pass a dummy econtext because none of the ExecEvalExpr() diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 0d32e82ed9a..055cd3788b9 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.61 2000/09/29 18:21:23 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.62 2000/11/16 22:30:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -48,9 +48,9 @@ relation_info(Oid relationObjectId, HeapTuple relationTuple; Form_pg_class relation; - relationTuple = SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(relationObjectId), - 0, 0, 0); + relationTuple = SearchSysCache(RELOID, + ObjectIdGetDatum(relationObjectId), + 0, 0, 0); if (!HeapTupleIsValid(relationTuple)) elog(ERROR, "relation_info: Relation %u not found", relationObjectId); @@ -62,6 +62,7 @@ relation_info(Oid relationObjectId, *hasindex = (relation->relhasindex) ? true : false; *pages = relation->relpages; *tuples = relation->reltuples; + ReleaseSysCache(relationTuple); } /* @@ -100,9 +101,9 @@ find_secondary_indexes(Oid relationObjectId) Oid relam; uint16 amorderstrategy; - indexTuple = SearchSysCacheTupleCopy(INDEXRELID, - ObjectIdGetDatum(indexoid), - 0, 0, 0); + indexTuple = SearchSysCache(INDEXRELID, + ObjectIdGetDatum(indexoid), + 0, 0, 0); if (!HeapTupleIsValid(indexTuple)) elog(ERROR, "find_secondary_indexes: index %u not found", indexoid); @@ -162,20 +163,22 @@ find_secondary_indexes(Oid relationObjectId) Form_pg_amop amop; amopTuple = - SearchSysCacheTuple(AMOPSTRATEGY, - ObjectIdGetDatum(relam), - ObjectIdGetDatum(index->indclass[i]), - UInt16GetDatum(amorderstrategy), - 0); + SearchSysCache(AMOPSTRATEGY, + ObjectIdGetDatum(relam), + ObjectIdGetDatum(index->indclass[i]), + UInt16GetDatum(amorderstrategy), + 0); if (!HeapTupleIsValid(amopTuple)) elog(ERROR, "find_secondary_indexes: no amop %u %u %d", - relam, index->indclass[i], (int) amorderstrategy); + relam, index->indclass[i], + (int) amorderstrategy); amop = (Form_pg_amop) GETSTRUCT(amopTuple); info->ordering[i] = amop->amopopr; + ReleaseSysCache(amopTuple); } } - heap_freetuple(indexTuple); + ReleaseSysCache(indexTuple); indexinfos = lcons(info, indexinfos); } @@ -315,13 +318,16 @@ find_inheritance_children(Oid inhparent) bool has_subclass(Oid relationId) { - HeapTuple tuple = - SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(relationId), - 0, 0, 0); + HeapTuple tuple; + bool result; + tuple = SearchSysCache(RELOID, + ObjectIdGetDatum(relationId), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "has_subclass: Relation %u not found", - relationId); - return ((Form_pg_class) GETSTRUCT(tuple))->relhassubclass; + elog(ERROR, "has_subclass: Relation %u not found", relationId); + + result = ((Form_pg_class) GETSTRUCT(tuple))->relhassubclass; + ReleaseSysCache(tuple); + return result; } diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 63f39f2e4cb..478ae973e5c 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: analyze.c,v 1.165 2000/11/08 22:09:58 tgl Exp $ + * $Id: analyze.c,v 1.166 2000/11/16 22:30:28 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2598,9 +2598,8 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint) Form_pg_attribute *pkrel_attrs; List *indexoidlist, *indexoidscan; - Form_pg_index indexStruct = NULL; int i; - int found=0; + bool found = false; /* ---------- * Open the referenced table and get the attributes list @@ -2616,7 +2615,7 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint) * Get the list of index OIDs for the table from the relcache, * and look up each one in the pg_index syscache for each unique * one, and then compare the attributes we were given to those - * defined. + * defined. * ---------- */ indexoidlist = RelationGetIndexList(pkrel); @@ -2625,27 +2624,34 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint) { Oid indexoid = lfirsti(indexoidscan); HeapTuple indexTuple; - List *attrl; - indexTuple = SearchSysCacheTuple(INDEXRELID, - ObjectIdGetDatum(indexoid), - 0, 0, 0); + Form_pg_index indexStruct; + + indexTuple = SearchSysCache(INDEXRELID, + ObjectIdGetDatum(indexoid), + 0, 0, 0); if (!HeapTupleIsValid(indexTuple)) elog(ERROR, "transformFkeyGetPrimaryKey: index %u not found", indexoid); indexStruct = (Form_pg_index) GETSTRUCT(indexTuple); - if (indexStruct->indisunique) { + if (indexStruct->indisunique) + { + List *attrl; + /* go through the fkconstraint->pk_attrs list */ - foreach(attrl, fkconstraint->pk_attrs) { + foreach(attrl, fkconstraint->pk_attrs) + { Ident *attr=lfirst(attrl); - found=0; + found = false; for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++) { int pkattno = indexStruct->indkey[i]; - if (pkattno>0) { + if (pkattno>0) + { char *name = NameStr(pkrel_attrs[pkattno - 1]->attname); - if (strcmp(name, attr->name)==0) { - found=1; + if (strcmp(name, attr->name)==0) + { + found = true; break; } } @@ -2654,9 +2660,9 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint) break; } } + ReleaseSysCache(indexTuple); if (found) break; - indexStruct = NULL; } if (!found) elog(ERROR, "UNIQUE constraint matching given keys for referenced table \"%s\" not found", @@ -2681,6 +2687,7 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint) Form_pg_attribute *pkrel_attrs; List *indexoidlist, *indexoidscan; + HeapTuple indexTuple = NULL; Form_pg_index indexStruct = NULL; int i; @@ -2705,17 +2712,17 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint) foreach(indexoidscan, indexoidlist) { Oid indexoid = lfirsti(indexoidscan); - HeapTuple indexTuple; - indexTuple = SearchSysCacheTuple(INDEXRELID, - ObjectIdGetDatum(indexoid), - 0, 0, 0); + indexTuple = SearchSysCache(INDEXRELID, + ObjectIdGetDatum(indexoid), + 0, 0, 0); if (!HeapTupleIsValid(indexTuple)) elog(ERROR, "transformFkeyGetPrimaryKey: index %u not found", indexoid); indexStruct = (Form_pg_index) GETSTRUCT(indexTuple); if (indexStruct->indisprimary) break; + ReleaseSysCache(indexTuple); indexStruct = NULL; } @@ -2747,6 +2754,8 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint) fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs, pkattr); } + ReleaseSysCache(indexTuple); + heap_close(pkrel, AccessShareLock); } @@ -2861,6 +2870,7 @@ static void transformColumnType(ParseState *pstate, ColumnDef *column) { TypeName *typename = column->typename; + Type ctype = typenameType(typename->name); /* * If the column doesn't have an explicitly specified typmod, check to @@ -2871,7 +2881,7 @@ transformColumnType(ParseState *pstate, ColumnDef *column) */ if (typename->typmod == -1) { - switch (typeTypeId(typenameType(typename->name))) + switch (typeTypeId(ctype)) { case BPCHAROID: /* "char" -> "char(1)" */ @@ -2891,11 +2901,13 @@ transformColumnType(ParseState *pstate, ColumnDef *column) * XXX this is a hangover from ancient Berkeley code that probably * doesn't work anymore anyway. */ - if (typeTypeRelid(typenameType(typename->name)) != InvalidOid) + if (typeTypeRelid(ctype) != InvalidOid) { /* (Eventually add in here that the set can only * contain one element.) */ typename->setof = true; } + + ReleaseSysCache(ctype); } diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c index e7d8fe8d3b7..1dc31dc1f07 100644 --- a/src/backend/parser/parse_agg.c +++ b/src/backend/parser/parse_agg.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.42 2000/09/29 18:21:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.43 2000/11/16 22:30:27 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -190,18 +190,18 @@ ParseAgg(ParseState *pstate, char *aggname, Oid basetype, List *args, bool agg_star, bool agg_distinct, int precedence) { - HeapTuple theAggTuple; + HeapTuple aggtuple; Form_pg_aggregate aggform; Aggref *aggref; - theAggTuple = SearchSysCacheTuple(AGGNAME, - PointerGetDatum(aggname), - ObjectIdGetDatum(basetype), - 0, 0); + aggtuple = SearchSysCache(AGGNAME, + PointerGetDatum(aggname), + ObjectIdGetDatum(basetype), + 0, 0); /* shouldn't happen --- caller should have checked already */ - if (!HeapTupleIsValid(theAggTuple)) + if (!HeapTupleIsValid(aggtuple)) agg_error("ParseAgg", aggname, basetype); - aggform = (Form_pg_aggregate) GETSTRUCT(theAggTuple); + aggform = (Form_pg_aggregate) GETSTRUCT(aggtuple); /* * There used to be a really ugly hack for count(*) here. @@ -225,6 +225,8 @@ ParseAgg(ParseState *pstate, char *aggname, Oid basetype, aggref->aggstar = agg_star; aggref->aggdistinct = agg_distinct; + ReleaseSysCache(aggtuple); + pstate->p_hasAggs = true; return aggref; diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index cbd19f0aae4..c8f55c98e84 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.72 2000/11/12 00:37:00 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.73 2000/11/16 22:30:27 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -953,9 +953,7 @@ transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist) grpcl->tleSortGroupRef = assignSortGroupRef(tle, targetlist); - grpcl->sortop = oprid(oper("<", - tle->resdom->restype, - tle->resdom->restype, false)); + grpcl->sortop = any_ordering_op(tle->resdom->restype); glist = lappend(glist, grpcl); } @@ -1151,9 +1149,10 @@ addTargetToSortList(TargetEntry *tle, List *sortlist, List *targetlist, sortcl->tleSortGroupRef = assignSortGroupRef(tle, targetlist); if (opname) - sortcl->sortop = oprid(oper(opname, - tle->resdom->restype, - tle->resdom->restype, false)); + sortcl->sortop = oper_oid(opname, + tle->resdom->restype, + tle->resdom->restype, + false); else sortcl->sortop = any_ordering_op(tle->resdom->restype); diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index f0d3427d17e..131d65cbcd0 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.48 2000/11/09 04:14:32 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.49 2000/11/16 22:30:27 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -84,6 +84,8 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId, pfree(val); } + ReleaseSysCache(targetType); + result = (Node *) newcon; } else if (IS_BINARY_COMPATIBLE(inputTypeId, targetTypeId)) @@ -124,9 +126,8 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId, * conversion function. */ FuncCall *n = makeNode(FuncCall); - Type targetType = typeidType(targetTypeId); - n->funcname = typeTypeName(targetType); + n->funcname = typeidTypeName(targetTypeId); n->args = lcons(node, NIL); n->agg_star = false; n->agg_distinct = false; @@ -136,7 +137,7 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId, /* safety check that we got the right thing */ if (exprType(result) != targetTypeId) elog(ERROR, "coerce_type: conversion function %s produced %s", - typeTypeName(targetType), + typeidTypeName(targetTypeId), typeidTypeName(exprType(result))); /* @@ -233,17 +234,21 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids) MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid)); oid_array[0] = inputTypeId; - ftup = SearchSysCacheTuple(PROCNAME, - PointerGetDatum(typeidTypeName(targetTypeId)), - Int32GetDatum(1), - PointerGetDatum(oid_array), - 0); + ftup = SearchSysCache(PROCNAME, + PointerGetDatum(typeidTypeName(targetTypeId)), + Int32GetDatum(1), + PointerGetDatum(oid_array), + 0); if (!HeapTupleIsValid(ftup)) return false; /* Make sure the function's result type is as expected, too */ pform = (Form_pg_proc) GETSTRUCT(ftup); if (pform->prorettype != targetTypeId) + { + ReleaseSysCache(ftup); return false; + } + ReleaseSysCache(ftup); } return true; @@ -272,7 +277,6 @@ coerce_type_typmod(ParseState *pstate, Node *node, { char *funcname; Oid oid_array[FUNC_MAX_ARGS]; - HeapTuple ftup; /* * We assume that only typmod values greater than 0 indicate a forced @@ -288,13 +292,11 @@ coerce_type_typmod(ParseState *pstate, Node *node, oid_array[1] = INT4OID; /* attempt to find with arguments exactly as specified... */ - ftup = SearchSysCacheTuple(PROCNAME, - PointerGetDatum(funcname), - Int32GetDatum(2), - PointerGetDatum(oid_array), - 0); - - if (HeapTupleIsValid(ftup)) + if (SearchSysCacheExists(PROCNAME, + PointerGetDatum(funcname), + Int32GetDatum(2), + PointerGetDatum(oid_array), + 0)) { A_Const *cons = makeNode(A_Const); FuncCall *func = makeNode(FuncCall); diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index ecf88ceea7e..97ed8123f67 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.87 2000/11/16 17:27:10 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.88 2000/11/16 22:30:28 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -386,7 +386,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) optup = oper(op, exprType(lexpr), exprType(tent->expr), - FALSE); + false); opform = (Form_pg_operator) GETSTRUCT(optup); if (opform->oprresult != BOOLOID) @@ -399,6 +399,7 @@ transformExpr(ParseState *pstate, Node *expr, int precedence) InvalidOid, /* opid */ opform->oprresult); sublink->oper = lappend(sublink->oper, newop); + ReleaseSysCache(optup); } if (left_list != NIL) elog(ERROR, "Subselect has too few fields"); @@ -740,7 +741,8 @@ exprIsLengthCoercion(Node *expr, int32 *coercedTypmod) { Func *func; Const *second_arg; - HeapTuple tup; + HeapTuple procTuple; + HeapTuple typeTuple; Form_pg_proc procStruct; Form_pg_type typeStruct; @@ -771,12 +773,12 @@ exprIsLengthCoercion(Node *expr, int32 *coercedTypmod) /* * Lookup the function in pg_proc */ - tup = SearchSysCacheTuple(PROCOID, - ObjectIdGetDatum(func->funcid), - 0, 0, 0); - if (!HeapTupleIsValid(tup)) + procTuple = SearchSysCache(PROCOID, + ObjectIdGetDatum(func->funcid), + 0, 0, 0); + if (!HeapTupleIsValid(procTuple)) elog(ERROR, "cache lookup for proc %u failed", func->funcid); - procStruct = (Form_pg_proc) GETSTRUCT(tup); + procStruct = (Form_pg_proc) GETSTRUCT(procTuple); /* * It must be a function with two arguments where the first is of the @@ -787,29 +789,39 @@ exprIsLengthCoercion(Node *expr, int32 *coercedTypmod) procStruct->prorettype != procStruct->proargtypes[0] || procStruct->proargtypes[1] != INT4OID || procStruct->prorettype != ((Expr *) expr)->typeOid) + { + ReleaseSysCache(procTuple); return false; + } /* * Furthermore, the name of the function must be the same as the * argument/result type's name. */ - tup = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(procStruct->prorettype), - 0, 0, 0); - if (!HeapTupleIsValid(tup)) + typeTuple = SearchSysCache(TYPEOID, + ObjectIdGetDatum(procStruct->prorettype), + 0, 0, 0); + if (!HeapTupleIsValid(typeTuple)) elog(ERROR, "cache lookup for type %u failed", procStruct->prorettype); - typeStruct = (Form_pg_type) GETSTRUCT(tup); + typeStruct = (Form_pg_type) GETSTRUCT(typeTuple); if (strncmp(NameStr(procStruct->proname), NameStr(typeStruct->typname), NAMEDATALEN) != 0) + { + ReleaseSysCache(procTuple); + ReleaseSysCache(typeTuple); return false; + } /* * OK, it is indeed a length-coercion function. */ if (coercedTypmod != NULL) *coercedTypmod = DatumGetInt32(second_arg->constvalue); + + ReleaseSysCache(procTuple); + ReleaseSysCache(typeTuple); return true; } @@ -865,6 +877,8 @@ parser_typecast_constant(Value *expr, TypeName *typename) if (string_palloced) pfree(const_string); + ReleaseSysCache(tp); + return (Node *) con; } @@ -881,11 +895,9 @@ parser_typecast_expression(ParseState *pstate, Node *expr, TypeName *typename) { Oid inputType = exprType(expr); - Type tp; Oid targetType; - tp = typenameType(TypeNameToInternalName(typename)); - targetType = typeTypeId(tp); + targetType = typenameTypeId(TypeNameToInternalName(typename)); if (inputType == InvalidOid) return expr; /* do nothing if NULL input */ diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index ea0544f701e..688c5bfa306 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.93 2000/11/11 19:49:26 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.94 2000/11/16 22:30:28 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -354,19 +354,19 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, CandidateList candidates; /* try for exact match first... */ - if (SearchSysCacheTuple(AGGNAME, - PointerGetDatum(funcname), - ObjectIdGetDatum(basetype), - 0, 0)) + if (SearchSysCacheExists(AGGNAME, + PointerGetDatum(funcname), + ObjectIdGetDatum(basetype), + 0, 0)) return (Node *) ParseAgg(pstate, funcname, basetype, fargs, agg_star, agg_distinct, precedence); /* check for aggregate-that-accepts-any-type (eg, COUNT) */ - if (SearchSysCacheTuple(AGGNAME, - PointerGetDatum(funcname), - ObjectIdGetDatum(0), - 0, 0)) + if (SearchSysCacheExists(AGGNAME, + PointerGetDatum(funcname), + ObjectIdGetDatum(0), + 0, 0)) return (Node *) ParseAgg(pstate, funcname, 0, fargs, agg_star, agg_distinct, precedence); @@ -450,7 +450,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, if (rte->relname == NULL) elog(ERROR, "function applied to tuple is not supported for subSELECTs"); - toid = typeTypeId(typenameType(rte->relname)); + toid = typenameTypeId(rte->relname); /* replace it in the arg list */ lfirst(i) = makeVar(vnum, 0, toid, -1, sublevels_up); @@ -531,15 +531,14 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, */ if (nargs == 1) { - Type tp; + Oid targetType; - tp = SearchSysCacheTuple(TYPENAME, - PointerGetDatum(funcname), - 0, 0, 0); - if (HeapTupleIsValid(tp)) + targetType = GetSysCacheOid(TYPENAME, + PointerGetDatum(funcname), + 0, 0, 0); + if (OidIsValid(targetType)) { Oid sourceType = oid_array[0]; - Oid targetType = typeTypeId(tp); Node *arg1 = lfirst(fargs); if ((sourceType == UNKNOWNOID && IsA(arg1, Const)) || @@ -573,6 +572,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, if (typeTypeFlag(tp) == 'c') elog(ERROR, "No such attribute or function '%s'", funcname); + ReleaseSysCache(tp); } /* Else generate a detailed complaint */ @@ -1037,11 +1037,11 @@ func_get_detail(char *funcname, HeapTuple ftup; /* attempt to find with arguments exactly as specified... */ - ftup = SearchSysCacheTuple(PROCNAME, - PointerGetDatum(funcname), - Int32GetDatum(nargs), - PointerGetDatum(argtypes), - 0); + ftup = SearchSysCache(PROCNAME, + PointerGetDatum(funcname), + Int32GetDatum(nargs), + PointerGetDatum(argtypes), + 0); if (HeapTupleIsValid(ftup)) { @@ -1085,11 +1085,11 @@ func_get_detail(char *funcname, if (ncandidates == 1) { *true_typeids = current_function_typeids->args; - ftup = SearchSysCacheTuple(PROCNAME, - PointerGetDatum(funcname), - Int32GetDatum(nargs), + ftup = SearchSysCache(PROCNAME, + PointerGetDatum(funcname), + Int32GetDatum(nargs), PointerGetDatum(*true_typeids), - 0); + 0); Assert(HeapTupleIsValid(ftup)); break; } @@ -1107,12 +1107,13 @@ func_get_detail(char *funcname, if (*true_typeids != NULL) { /* was able to choose a best candidate */ - ftup = SearchSysCacheTuple(PROCNAME, - PointerGetDatum(funcname), - Int32GetDatum(nargs), - PointerGetDatum(*true_typeids), - 0); + ftup = SearchSysCache(PROCNAME, + PointerGetDatum(funcname), + Int32GetDatum(nargs), + PointerGetDatum(*true_typeids), + 0); Assert(HeapTupleIsValid(ftup)); + break; } /* @@ -1143,6 +1144,7 @@ func_get_detail(char *funcname, *funcid = ftup->t_data->t_oid; *rettype = pform->prorettype; *retset = pform->proretset; + ReleaseSysCache(ftup); return true; } return false; @@ -1284,7 +1286,7 @@ find_inheritors(Oid relid, Oid **supervec) relid = lfirsti(elt); rd = heap_open(relid, NoLock); - trelid = typeTypeId(typenameType(RelationGetRelationName(rd))); + trelid = typenameTypeId(RelationGetRelationName(rd)); heap_close(rd, NoLock); *relidvec++ = trelid; } diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c index d23c5c1e7c7..1d846bd4bba 100644 --- a/src/backend/parser/parse_node.c +++ b/src/backend/parser/parse_node.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.48 2000/10/31 10:22:11 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.49 2000/11/16 22:30:28 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -67,7 +67,6 @@ make_operand(char *opname, Oid target_typeId) { Node *result; - Type target_type = typeidType(target_typeId); if (tree != NULL) { @@ -80,15 +79,7 @@ make_operand(char *opname, else { /* otherwise, this is a NULL value */ - Const *con = makeNode(Const); - - con->consttype = target_typeId; - con->constlen = typeLen(target_type); - con->constvalue = (Datum) NULL; - con->constisnull = true; - con->constbyval = typeByVal(target_type); - con->constisset = false; - result = (Node *) con; + result = (Node *) makeNullConst(target_typeId); } return result; @@ -137,7 +128,7 @@ make_op(char *opname, Node *ltree, Node *rtree) /* otherwise, binary operator */ else { - tup = oper(opname, ltypeId, rtypeId, FALSE); + tup = oper(opname, ltypeId, rtypeId, false); opform = (Form_pg_operator) GETSTRUCT(tup); left = make_operand(opname, ltree, ltypeId, opform->oprleft); right = make_operand(opname, rtree, rtypeId, opform->oprright); @@ -159,6 +150,8 @@ make_op(char *opname, Node *ltree, Node *rtree) else result->args = makeList2(left, right); + ReleaseSysCache(tup); + return result; } /* make_op() */ @@ -183,10 +176,10 @@ make_var(ParseState *pstate, RangeTblEntry *rte, int attrno) HeapTuple tp; Form_pg_attribute att_tup; - tp = SearchSysCacheTuple(ATTNUM, - ObjectIdGetDatum(rte->relid), - Int16GetDatum(attrno), - 0, 0); + tp = SearchSysCache(ATTNUM, + ObjectIdGetDatum(rte->relid), + Int16GetDatum(attrno), + 0, 0); /* this shouldn't happen... */ if (!HeapTupleIsValid(tp)) elog(ERROR, "Relation %s does not have attribute %d", @@ -194,6 +187,7 @@ make_var(ParseState *pstate, RangeTblEntry *rte, int attrno) att_tup = (Form_pg_attribute) GETSTRUCT(tp); vartypeid = att_tup->atttypid; type_mod = att_tup->atttypmod; + ReleaseSysCache(tp); } else { @@ -249,7 +243,8 @@ transformArraySubscripts(ParseState *pstate, Oid typearray, typeelement, typeresult; - HeapTuple type_tuple; + HeapTuple type_tuple_array, + type_tuple_element; Form_pg_type type_struct_array, type_struct_element; bool isSlice = forceSlice; @@ -261,13 +256,13 @@ transformArraySubscripts(ParseState *pstate, /* Get the type tuple for the array */ typearray = exprType(arrayBase); - type_tuple = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(typearray), - 0, 0, 0); - if (!HeapTupleIsValid(type_tuple)) + type_tuple_array = SearchSysCache(TYPEOID, + ObjectIdGetDatum(typearray), + 0, 0, 0); + if (!HeapTupleIsValid(type_tuple_array)) elog(ERROR, "transformArraySubscripts: Cache lookup failed for array type %u", typearray); - type_struct_array = (Form_pg_type) GETSTRUCT(type_tuple); + type_struct_array = (Form_pg_type) GETSTRUCT(type_tuple_array); typeelement = type_struct_array->typelem; if (typeelement == InvalidOid) @@ -275,13 +270,13 @@ transformArraySubscripts(ParseState *pstate, NameStr(type_struct_array->typname)); /* Get the type tuple for the array element type */ - type_tuple = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(typeelement), - 0, 0, 0); - if (!HeapTupleIsValid(type_tuple)) + type_tuple_element = SearchSysCache(TYPEOID, + ObjectIdGetDatum(typeelement), + 0, 0, 0); + if (!HeapTupleIsValid(type_tuple_element)) elog(ERROR, "transformArraySubscripts: Cache lookup failed for array element type %u", typeelement); - type_struct_element = (Form_pg_type) GETSTRUCT(type_tuple); + type_struct_element = (Form_pg_type) GETSTRUCT(type_tuple_element); /* * A list containing only single subscripts refers to a single array @@ -398,6 +393,9 @@ transformArraySubscripts(ParseState *pstate, aref->refexpr = arrayBase; aref->refassgnexpr = assignFrom; + ReleaseSysCache(type_tuple_array); + ReleaseSysCache(type_tuple_element); + return aref; } diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c index 7d3919a1fc6..a44a740dc92 100644 --- a/src/backend/parser/parse_oper.c +++ b/src/backend/parser/parse_oper.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.43 2000/11/11 19:49:26 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.44 2000/11/16 22:30:28 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -38,25 +38,21 @@ static void op_error(char *op, Oid arg1, Oid arg2); static void unary_op_error(char *op, Oid arg, bool is_left_op); +/* Select an ordering operator for the given datatype */ Oid any_ordering_op(Oid restype) { - Operator order_op; Oid order_opid; - order_op = oper("<", restype, restype, TRUE); - if (!HeapTupleIsValid(order_op)) - { + order_opid = oper_oid("<", restype, restype, true); + if (!OidIsValid(order_opid)) elog(ERROR, "Unable to identify an ordering operator '%s' for type '%s'" "\n\tUse an explicit ordering operator or modify the query", "<", typeidTypeName(restype)); - } - order_opid = oprid(order_op); - return order_opid; } -/* given operator, return the operator OID */ +/* given operator tuple, return the operator OID */ Oid oprid(Operator op) { @@ -502,9 +498,10 @@ oper_select_candidate(int nargs, /* oper_exact() - * Given operator, and arguments, return oper struct or NULL. - * Inputs: - * arg1, arg2: Type IDs + * Given operator, types of arg1 and arg2, return oper struct or NULL. + * + * NOTE: on success, the returned object is a syscache entry. The caller + * must ReleaseSysCache() the entry when done with it. */ static Operator oper_exact(char *op, Oid arg1, Oid arg2) @@ -517,20 +514,21 @@ oper_exact(char *op, Oid arg1, Oid arg2) else if ((arg2 == UNKNOWNOID) && (arg1 != InvalidOid)) arg2 = arg1; - tup = SearchSysCacheTuple(OPERNAME, - PointerGetDatum(op), - ObjectIdGetDatum(arg1), - ObjectIdGetDatum(arg2), - CharGetDatum('b')); + tup = SearchSysCache(OPERNAME, + PointerGetDatum(op), + ObjectIdGetDatum(arg1), + ObjectIdGetDatum(arg2), + CharGetDatum('b')); return (Operator) tup; -} /* oper_exact() */ +} /* oper_inexact() - * Given operator, types of arg1, and arg2, return oper struct or NULL. - * Inputs: - * arg1, arg2: Type IDs + * Given operator, types of arg1 and arg2, return oper struct or NULL. + * + * NOTE: on success, the returned object is a syscache entry. The caller + * must ReleaseSysCache() the entry when done with it. */ static Operator oper_inexact(char *op, Oid arg1, Oid arg2) @@ -556,11 +554,11 @@ oper_inexact(char *op, Oid arg1, Oid arg2) /* Or found exactly one? Then proceed... */ else if (ncandidates == 1) { - tup = SearchSysCacheTuple(OPERNAME, - PointerGetDatum(op), - ObjectIdGetDatum(candidates->args[0]), - ObjectIdGetDatum(candidates->args[1]), - CharGetDatum('b')); + tup = SearchSysCache(OPERNAME, + PointerGetDatum(op), + ObjectIdGetDatum(candidates->args[0]), + ObjectIdGetDatum(candidates->args[1]), + CharGetDatum('b')); Assert(HeapTupleIsValid(tup)); } @@ -572,43 +570,68 @@ oper_inexact(char *op, Oid arg1, Oid arg2) targetOids = oper_select_candidate(2, inputOids, candidates); if (targetOids != NULL) { - tup = SearchSysCacheTuple(OPERNAME, - PointerGetDatum(op), - ObjectIdGetDatum(targetOids[0]), - ObjectIdGetDatum(targetOids[1]), - CharGetDatum('b')); + tup = SearchSysCache(OPERNAME, + PointerGetDatum(op), + ObjectIdGetDatum(targetOids[0]), + ObjectIdGetDatum(targetOids[1]), + CharGetDatum('b')); } else tup = NULL; } return (Operator) tup; -} /* oper_inexact() */ +} -/* oper() - * Given operator, types of arg1, and arg2, return oper struct. - * Inputs: - * arg1, arg2: Type IDs +/* oper() -- search for a binary operator + * Given operator name, types of arg1 and arg2, return oper struct. + * + * If no matching operator found, return NULL if noError is true, + * raise an error if it is false. + * + * NOTE: on success, the returned object is a syscache entry. The caller + * must ReleaseSysCache() the entry when done with it. */ Operator -oper(char *opname, Oid ltypeId, Oid rtypeId, bool noWarnings) +oper(char *opname, Oid ltypeId, Oid rtypeId, bool noError) { HeapTuple tup; /* check for exact match on this operator... */ if (HeapTupleIsValid(tup = oper_exact(opname, ltypeId, rtypeId))) - { - } + return (Operator) tup; + /* try to find a match on likely candidates... */ - else if (HeapTupleIsValid(tup = oper_inexact(opname, ltypeId, rtypeId))) - { - } - else if (!noWarnings) + if (HeapTupleIsValid(tup = oper_inexact(opname, ltypeId, rtypeId))) + return (Operator) tup; + + if (!noError) op_error(opname, ltypeId, rtypeId); - return (Operator) tup; -} /* oper() */ + return (Operator) NULL; +} + +/* oper_oid() -- get OID of a binary operator + * + * This is a convenience routine that extracts only the operator OID + * from the result of oper(). InvalidOid is returned if the lookup + * fails and noError is true. + */ +Oid +oper_oid(char *op, Oid arg1, Oid arg2, bool noError) +{ + Operator optup; + Oid result; + optup = oper(op, arg1, arg2, noError); + if (optup != NULL) + { + result = oprid(optup); + ReleaseSysCache(optup); + return result; + } + return InvalidOid; +} /* unary_oper_get_candidates() * given opname, find all possible types for which @@ -671,8 +694,13 @@ unary_oper_get_candidates(char *opname, } /* unary_oper_get_candidates() */ -/* Given unary right-side operator (operator on right), return oper struct */ -/* arg-- type id */ +/* Given unary right operator (operator on right), return oper struct + * + * Always raises error on failure. + * + * NOTE: on success, the returned object is a syscache entry. The caller + * must ReleaseSysCache() the entry when done with it. + */ Operator right_oper(char *op, Oid arg) { @@ -682,11 +710,11 @@ right_oper(char *op, Oid arg) Oid *targetOid; /* Try for exact match */ - tup = SearchSysCacheTuple(OPERNAME, - PointerGetDatum(op), - ObjectIdGetDatum(arg), - ObjectIdGetDatum(InvalidOid), - CharGetDatum('r')); + tup = SearchSysCache(OPERNAME, + PointerGetDatum(op), + ObjectIdGetDatum(arg), + ObjectIdGetDatum(InvalidOid), + CharGetDatum('r')); if (!HeapTupleIsValid(tup)) { @@ -696,21 +724,21 @@ right_oper(char *op, Oid arg) unary_op_error(op, arg, FALSE); else if (ncandidates == 1) { - tup = SearchSysCacheTuple(OPERNAME, - PointerGetDatum(op), - ObjectIdGetDatum(candidates->args[0]), - ObjectIdGetDatum(InvalidOid), - CharGetDatum('r')); + tup = SearchSysCache(OPERNAME, + PointerGetDatum(op), + ObjectIdGetDatum(candidates->args[0]), + ObjectIdGetDatum(InvalidOid), + CharGetDatum('r')); } else { targetOid = oper_select_candidate(1, &arg, candidates); if (targetOid != NULL) - tup = SearchSysCacheTuple(OPERNAME, - PointerGetDatum(op), - ObjectIdGetDatum(targetOid[0]), - ObjectIdGetDatum(InvalidOid), - CharGetDatum('r')); + tup = SearchSysCache(OPERNAME, + PointerGetDatum(op), + ObjectIdGetDatum(targetOid[0]), + ObjectIdGetDatum(InvalidOid), + CharGetDatum('r')); } if (!HeapTupleIsValid(tup)) @@ -721,8 +749,13 @@ right_oper(char *op, Oid arg) } /* right_oper() */ -/* Given unary left-side operator (operator on left), return oper struct */ -/* arg--type id */ +/* Given unary left operator (operator on left), return oper struct + * + * Always raises error on failure. + * + * NOTE: on success, the returned object is a syscache entry. The caller + * must ReleaseSysCache() the entry when done with it. + */ Operator left_oper(char *op, Oid arg) { @@ -732,11 +765,11 @@ left_oper(char *op, Oid arg) Oid *targetOid; /* Try for exact match */ - tup = SearchSysCacheTuple(OPERNAME, - PointerGetDatum(op), - ObjectIdGetDatum(InvalidOid), - ObjectIdGetDatum(arg), - CharGetDatum('l')); + tup = SearchSysCache(OPERNAME, + PointerGetDatum(op), + ObjectIdGetDatum(InvalidOid), + ObjectIdGetDatum(arg), + CharGetDatum('l')); if (!HeapTupleIsValid(tup)) { @@ -746,21 +779,21 @@ left_oper(char *op, Oid arg) unary_op_error(op, arg, TRUE); else if (ncandidates == 1) { - tup = SearchSysCacheTuple(OPERNAME, - PointerGetDatum(op), - ObjectIdGetDatum(InvalidOid), - ObjectIdGetDatum(candidates->args[0]), - CharGetDatum('l')); + tup = SearchSysCache(OPERNAME, + PointerGetDatum(op), + ObjectIdGetDatum(InvalidOid), + ObjectIdGetDatum(candidates->args[0]), + CharGetDatum('l')); } else { targetOid = oper_select_candidate(1, &arg, candidates); if (targetOid != NULL) - tup = SearchSysCacheTuple(OPERNAME, - PointerGetDatum(op), - ObjectIdGetDatum(InvalidOid), - ObjectIdGetDatum(targetOid[0]), - CharGetDatum('l')); + tup = SearchSysCache(OPERNAME, + PointerGetDatum(op), + ObjectIdGetDatum(InvalidOid), + ObjectIdGetDatum(targetOid[0]), + CharGetDatum('l')); } if (!HeapTupleIsValid(tup)) @@ -778,24 +811,17 @@ left_oper(char *op, Oid arg) static void op_error(char *op, Oid arg1, Oid arg2) { - Type tp1 = NULL, - tp2 = NULL; - - if (typeidIsValid(arg1)) - tp1 = typeidType(arg1); - else + if (!typeidIsValid(arg1)) elog(ERROR, "Left hand side of operator '%s' has an unknown type" "\n\tProbably a bad attribute name", op); - if (typeidIsValid(arg2)) - tp2 = typeidType(arg2); - else + if (!typeidIsValid(arg2)) elog(ERROR, "Right hand side of operator %s has an unknown type" "\n\tProbably a bad attribute name", op); elog(ERROR, "Unable to identify an operator '%s' for types '%s' and '%s'" "\n\tYou will have to retype this query using an explicit cast", - op, typeTypeName(tp1), typeTypeName(tp2)); + op, typeidTypeName(arg1), typeidTypeName(arg2)); } /* unary_op_error() @@ -805,20 +831,14 @@ op_error(char *op, Oid arg1, Oid arg2) static void unary_op_error(char *op, Oid arg, bool is_left_op) { - Type tp1 = NULL; - - if (typeidIsValid(arg)) - tp1 = typeidType(arg); - else - { + if (!typeidIsValid(arg)) elog(ERROR, "Argument of %s operator '%s' has an unknown type" "\n\tProbably a bad attribute name", (is_left_op ? "left" : "right"), op); - } elog(ERROR, "Unable to identify a %s operator '%s' for type '%s'" "\n\tYou may need to add parentheses or an explicit cast", (is_left_op ? "left" : "right"), - op, typeTypeName(tp1)); + op, typeidTypeName(arg)); } diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c index c582bd54abe..5a699624097 100644 --- a/src/backend/parser/parse_type.c +++ b/src/backend/parser/parse_type.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.32 2000/06/08 22:37:18 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.33 2000/11/16 22:30:28 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -28,63 +28,45 @@ bool typeidIsValid(Oid id) { - return (SearchSysCacheTuple(TYPEOID, + return SearchSysCacheExists(TYPEOID, ObjectIdGetDatum(id), - 0, 0, 0) != NULL); -} - -/* return a type name, given a typeid */ -char * -typeidTypeName(Oid id) -{ - HeapTuple tup; - Form_pg_type typetuple; - - if (!(tup = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(id), - 0, 0, 0))) - { - elog(ERROR, "Unable to locate type oid %u in catalog", id); - return NULL; - } - typetuple = (Form_pg_type) GETSTRUCT(tup); - /* pstrdup here because result may need to outlive the syscache entry */ - return pstrdup(NameStr(typetuple->typname)); + 0, 0, 0); } /* return a Type structure, given a type id */ +/* NB: caller must ReleaseSysCache the type tuple when done with it */ Type typeidType(Oid id) { HeapTuple tup; - if (!(tup = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(id), - 0, 0, 0))) - { + tup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(id), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) elog(ERROR, "Unable to locate type oid %u in catalog", id); - return NULL; - } return (Type) tup; } /* return a Type structure, given type name */ +/* NB: caller must ReleaseSysCache the type tuple when done with it */ Type typenameType(char *s) { HeapTuple tup; if (s == NULL) - elog(ERROR, "type(): Null type"); + elog(ERROR, "typenameType: Null typename"); - if (!(tup = SearchSysCacheTuple(TYPENAME, - PointerGetDatum(s), - 0, 0, 0))) + tup = SearchSysCache(TYPENAME, + PointerGetDatum(s), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) elog(ERROR, "Unable to locate type name '%s' in catalog", s); return (Type) tup; } -/* given type, return the type OID */ +/* given type (as type struct), return the type OID */ Oid typeTypeId(Type tp) { @@ -134,6 +116,54 @@ typeTypeFlag(Type t) return typ->typtype; } +Oid +typeTypeRelid(Type typ) +{ + Form_pg_type typtup; + + typtup = (Form_pg_type) GETSTRUCT(typ); + + return typtup->typrelid; +} + +#ifdef NOT_USED +Oid +typeTypElem(Type typ) +{ + Form_pg_type typtup; + + typtup = (Form_pg_type) GETSTRUCT(typ); + + return typtup->typelem; +} +#endif + +#ifdef NOT_USED +/* Given a type structure, return the in-conversion function of the type */ +Oid +typeInfunc(Type typ) +{ + Form_pg_type typtup; + + typtup = (Form_pg_type) GETSTRUCT(typ); + + return typtup->typinput; +} +#endif + +#ifdef NOT_USED +/* Given a type structure, return the out-conversion function of the type */ +Oid +typeOutfunc(Type typ) +{ + Form_pg_type typtup; + + typtup = (Form_pg_type) GETSTRUCT(typ); + + return typtup->typoutput; +} +#endif + /* Given a type structure and a string, returns the internal form of that string */ Datum @@ -160,109 +190,72 @@ typeidOutfunc(Oid type_id) Form_pg_type type; Oid outfunc; - typeTuple = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(type_id), - 0, 0, 0); + typeTuple = SearchSysCache(TYPEOID, + ObjectIdGetDatum(type_id), + 0, 0, 0); if (!HeapTupleIsValid(typeTuple)) elog(ERROR, "typeidOutfunc: Invalid type - oid = %u", type_id); type = (Form_pg_type) GETSTRUCT(typeTuple); outfunc = type->typoutput; + ReleaseSysCache(typeTuple); return outfunc; } #endif +/* return a type name, given a typeid */ +char * +typeidTypeName(Oid id) +{ + HeapTuple tup; + Form_pg_type typetuple; + char *result; + + tup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(id), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) + elog(ERROR, "Unable to locate type oid %u in catalog", id); + typetuple = (Form_pg_type) GETSTRUCT(tup); + /* + * pstrdup here because result may need to outlive the syscache entry + * (eg, it might end up as part of a parse tree that will outlive + * the current transaction...) + */ + result = pstrdup(NameStr(typetuple->typname)); + ReleaseSysCache(tup); + return result; +} + +/* given a typeid, return the type's typrelid (associated relation, if any) */ Oid typeidTypeRelid(Oid type_id) { HeapTuple typeTuple; Form_pg_type type; + Oid result; - typeTuple = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(type_id), - 0, 0, 0); + typeTuple = SearchSysCache(TYPEOID, + ObjectIdGetDatum(type_id), + 0, 0, 0); if (!HeapTupleIsValid(typeTuple)) elog(ERROR, "typeidTypeRelid: Invalid type - oid = %u", type_id); type = (Form_pg_type) GETSTRUCT(typeTuple); - return type->typrelid; -} - -Oid -typeTypeRelid(Type typ) -{ - Form_pg_type typtup; - - typtup = (Form_pg_type) GETSTRUCT(typ); - - return typtup->typrelid; -} - -#ifdef NOT_USED -Oid -typeTypElem(Type typ) -{ - Form_pg_type typtup; - - typtup = (Form_pg_type) GETSTRUCT(typ); - - return typtup->typelem; -} -#endif - -#ifdef NOT_USED -/* Given the attribute type of an array return the attribute type of - an element of the array */ -Oid -GetArrayElementType(Oid typearray) -{ - HeapTuple type_tuple; - Form_pg_type type_struct_array; - - type_tuple = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(typearray), - 0, 0, 0); - - if (!HeapTupleIsValid(type_tuple)) - elog(ERROR, "GetArrayElementType: Cache lookup failed for type %u", - typearray); - - /* get the array type struct from the type tuple */ - type_struct_array = (Form_pg_type) GETSTRUCT(type_tuple); - - if (type_struct_array->typelem == InvalidOid) - { - elog(ERROR, "GetArrayElementType: type %s is not an array", - NameStr(type_struct_array->typname)); - } - - return type_struct_array->typelem; + result = type->typrelid; + ReleaseSysCache(typeTuple); + return result; } -#endif -#ifdef NOT_USED -/* Given a type structure, return the in-conversion function of the type */ +/* given a type name, return the type's typeid */ Oid -typeInfunc(Type typ) +typenameTypeId(char *s) { - Form_pg_type typtup; - - typtup = (Form_pg_type) GETSTRUCT(typ); + Type typ = typenameType(s); + Oid result; - return typtup->typinput; + result = typ->t_data->t_oid; + ReleaseSysCache(typ); + return result; } -#endif - -#ifdef NOT_USED -/* Given a type structure, return the out-conversion function of the type */ -Oid -typeOutfunc(Type typ) -{ - Form_pg_type typtup; - - typtup = (Form_pg_type) GETSTRUCT(typ); - - return typtup->typoutput; -} -#endif diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c index cffe624deb4..3e1f8f4a68d 100644 --- a/src/backend/rewrite/rewriteManip.c +++ b/src/backend/rewrite/rewriteManip.c @@ -7,12 +7,13 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.50 2000/10/05 19:11:34 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.51 2000/11/16 22:30:29 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" +#include "nodes/makefuncs.h" #include "optimizer/clauses.h" #include "optimizer/tlist.h" #include "parser/parsetree.h" @@ -555,20 +556,6 @@ AddNotQual(Query *parsetree, Node *qual) } -/* Build a NULL constant expression of the given type */ -static Node * -make_null(Oid type) -{ - Const *c = makeNode(Const); - - c->consttype = type; - c->constlen = get_typlen(type); - c->constvalue = PointerGetDatum(NULL); - c->constisnull = true; - c->constbyval = get_typbyval(type); - return (Node *) c; -} - /* Find a targetlist entry by resno */ static Node * FindMatchingNew(List *tlist, int attno) @@ -656,7 +643,7 @@ ResolveNew_mutator(Node *node, ResolveNew_context *context) else { /* Otherwise replace unmatched var with a null */ - return make_null(var->vartype); + return (Node *) makeNullConst(var->vartype); } } else @@ -796,7 +783,7 @@ HandleRIRAttributeRule_mutator(Node *node, { /* HACK: disallow SET variables */ *context->modified = TRUE; *context->badsql = TRUE; - return make_null(var->vartype); + return (Node *) makeNullConst(var->vartype); } else { @@ -813,7 +800,7 @@ HandleRIRAttributeRule_mutator(Node *node, n = FindMatchingTLEntry(context->targetlist, name_to_look_for); if (n == NULL) - return make_null(var->vartype); + return (Node *) makeNullConst(var->vartype); /* Make a copy of the tlist item to return */ n = copyObject(n); diff --git a/src/backend/rewrite/rewriteRemove.c b/src/backend/rewrite/rewriteRemove.c index ba409f4fbf6..760614461cd 100644 --- a/src/backend/rewrite/rewriteRemove.c +++ b/src/backend/rewrite/rewriteRemove.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.40 2000/09/29 18:21:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.41 2000/11/16 22:30:29 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -35,21 +35,26 @@ RewriteGetRuleEventRel(char *rulename) { HeapTuple htup; Oid eventrel; + char *result; - htup = SearchSysCacheTuple(RULENAME, - PointerGetDatum(rulename), - 0, 0, 0); + htup = SearchSysCache(RULENAME, + PointerGetDatum(rulename), + 0, 0, 0); if (!HeapTupleIsValid(htup)) elog(ERROR, "Rule or view \"%s\" not found", ((strncmp(rulename, "_RET", 4) == 0) ? (rulename + 4) : rulename)); eventrel = ((Form_pg_rewrite) GETSTRUCT(htup))->ev_class; - htup = SearchSysCacheTuple(RELOID, - PointerGetDatum(eventrel), - 0, 0, 0); + ReleaseSysCache(htup); + + htup = SearchSysCache(RELOID, + PointerGetDatum(eventrel), + 0, 0, 0); if (!HeapTupleIsValid(htup)) elog(ERROR, "Relation %u not found", eventrel); - return NameStr(((Form_pg_class) GETSTRUCT(htup))->relname); + result = pstrdup(NameStr(((Form_pg_class) GETSTRUCT(htup))->relname)); + ReleaseSysCache(htup); + return result; } /* @@ -75,9 +80,9 @@ RemoveRewriteRule(char *ruleName) /* * Find the tuple for the target rule. */ - tuple = SearchSysCacheTupleCopy(RULENAME, - PointerGetDatum(ruleName), - 0, 0, 0); + tuple = SearchSysCacheCopy(RULENAME, + PointerGetDatum(ruleName), + 0, 0, 0); /* * complain if no rule with such name existed diff --git a/src/backend/rewrite/rewriteSupport.c b/src/backend/rewrite/rewriteSupport.c index 264021da223..30e4ba6e603 100644 --- a/src/backend/rewrite/rewriteSupport.c +++ b/src/backend/rewrite/rewriteSupport.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.44 2000/09/29 18:21:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.45 2000/11/16 22:30:29 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -18,19 +18,15 @@ #include "catalog/catname.h" #include "catalog/indexing.h" #include "rewrite/rewriteSupport.h" -#include "utils/catcache.h" #include "utils/syscache.h" -int +bool IsDefinedRewriteRule(char *ruleName) { - HeapTuple tuple; - - tuple = SearchSysCacheTuple(RULENAME, + return SearchSysCacheExists(RULENAME, PointerGetDatum(ruleName), 0, 0, 0); - return HeapTupleIsValid(tuple); } /* @@ -59,10 +55,11 @@ SetRelationRuleStatus(Oid relationId, bool relHasRules, * Find the tuple to update in pg_class, using syscache for the lookup. */ relationRelation = heap_openr(RelationRelationName, RowExclusiveLock); - tuple = SearchSysCacheTupleCopy(RELOID, - ObjectIdGetDatum(relationId), - 0, 0, 0); - Assert(HeapTupleIsValid(tuple)); + tuple = SearchSysCacheCopy(RELOID, + ObjectIdGetDatum(relationId), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "SetRelationRuleStatus: cache lookup failed for relation %u", relationId); /* Do the update */ ((Form_pg_class) GETSTRUCT(tuple))->relhasrules = relHasRules; diff --git a/src/backend/tcop/fastpath.c b/src/backend/tcop/fastpath.c index 05640b5be8f..c888ea012ac 100644 --- a/src/backend/tcop/fastpath.c +++ b/src/backend/tcop/fastpath.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.44 2000/10/24 20:59:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.45 2000/11/16 22:30:30 tgl Exp $ * * NOTES * This cruft is the server side of PQfn. @@ -202,14 +202,12 @@ update_fp_info(Oid func_id, struct fp_info * fip) MemSet((char *) fip, 0, (int) sizeof(struct fp_info)); fip->funcid = InvalidOid; - func_htp = SearchSysCacheTuple(PROCOID, - ObjectIdGetDatum(func_id), - 0, 0, 0); + func_htp = SearchSysCache(PROCOID, + ObjectIdGetDatum(func_id), + 0, 0, 0); if (!HeapTupleIsValid(func_htp)) - { elog(ERROR, "update_fp_info: cache lookup for function %u failed", func_id); - } pp = (Form_pg_proc) GETSTRUCT(func_htp); rettype = pp->prorettype; argtypes = pp->proargtypes; @@ -220,38 +218,38 @@ update_fp_info(Oid func_id, struct fp_info * fip) { if (OidIsValid(argtypes[i])) { - type_htp = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(argtypes[i]), - 0, 0, 0); + type_htp = SearchSysCache(TYPEOID, + ObjectIdGetDatum(argtypes[i]), + 0, 0, 0); if (!HeapTupleIsValid(type_htp)) - { elog(ERROR, "update_fp_info: bad argument type %u for %u", argtypes[i], func_id); - } tp = (Form_pg_type) GETSTRUCT(type_htp); fip->argbyval[i] = tp->typbyval; fip->arglen[i] = tp->typlen; + ReleaseSysCache(type_htp); } /* else it had better be VAR_LENGTH_ARG */ } if (OidIsValid(rettype)) { - type_htp = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(rettype), - 0, 0, 0); + type_htp = SearchSysCache(TYPEOID, + ObjectIdGetDatum(rettype), + 0, 0, 0); if (!HeapTupleIsValid(type_htp)) - { elog(ERROR, "update_fp_info: bad return type %u for %u", rettype, func_id); - } tp = (Form_pg_type) GETSTRUCT(type_htp); fip->retbyval = tp->typbyval; fip->retlen = tp->typlen; + ReleaseSysCache(type_htp); } /* else it had better by VAR_LENGTH_RESULT */ fip->xid = GetCurrentTransactionId(); fip->cid = GetCurrentCommandId(); + ReleaseSysCache(func_htp); + /* * This must be last! */ diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 63a43315286..e725ff391f4 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.102 2000/11/14 18:37:43 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.103 2000/11/16 22:30:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -102,9 +102,9 @@ CheckDropPermissions(char *name, char rightkind) break; Assert(rentry->kind != '\0'); - tuple = SearchSysCacheTuple(RELNAME, - PointerGetDatum(name), - 0, 0, 0); + tuple = SearchSysCache(RELNAME, + PointerGetDatum(name), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "%s \"%s\" does not exist", rentry->name, name); @@ -120,6 +120,8 @@ CheckDropPermissions(char *name, char rightkind) if (!allowSystemTableMods && IsSystemRelationName(name)) elog(ERROR, "%s \"%s\" is a system %s", rentry->name, name, rentry->name); + + ReleaseSysCache(tuple); } diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index 1a2b2ef953e..a8bc5e349a3 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.52 2000/11/03 19:01:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.53 2000/11/16 22:30:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -174,12 +174,13 @@ aclparse(char *s, AclItem *aip, unsigned *modechg) switch (aip->ai_idtype) { case ACL_IDTYPE_UID: - htup = SearchSysCacheTuple(SHADOWNAME, - PointerGetDatum(name), - 0, 0, 0); + htup = SearchSysCache(SHADOWNAME, + PointerGetDatum(name), + 0, 0, 0); if (!HeapTupleIsValid(htup)) elog(ERROR, "aclparse: non-existent user \"%s\"", name); aip->ai_id = ((Form_pg_shadow) GETSTRUCT(htup))->usesysid; + ReleaseSysCache(htup); break; case ACL_IDTYPE_GID: aip->ai_id = get_grosysid(name); @@ -272,9 +273,9 @@ aclitemout(PG_FUNCTION_ARGS) switch (aip->ai_idtype) { case ACL_IDTYPE_UID: - htup = SearchSysCacheTuple(SHADOWSYSID, - ObjectIdGetDatum(aip->ai_id), - 0, 0, 0); + htup = SearchSysCache(SHADOWSYSID, + ObjectIdGetDatum(aip->ai_id), + 0, 0, 0); if (!HeapTupleIsValid(htup)) { /* Generate numeric UID if we don't find an entry */ @@ -286,9 +287,12 @@ aclitemout(PG_FUNCTION_ARGS) pfree(tmp); } else + { strncat(p, (char *) &((Form_pg_shadow) GETSTRUCT(htup))->usename, sizeof(NameData)); + ReleaseSysCache(htup); + } break; case ACL_IDTYPE_GID: strcat(p, "group "); diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index 44f58840c36..47c1b814c4d 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.65 2000/11/14 23:28:13 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.66 2000/11/16 22:30:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1590,9 +1590,9 @@ system_cache_lookup(Oid element_type, HeapTuple typeTuple; Form_pg_type typeStruct; - typeTuple = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(element_type), - 0, 0, 0); + typeTuple = SearchSysCache(TYPEOID, + ObjectIdGetDatum(element_type), + 0, 0, 0); if (!HeapTupleIsValid(typeTuple)) elog(ERROR, "array_out: Cache lookup failed for type %u", element_type); @@ -1607,6 +1607,7 @@ system_cache_lookup(Oid element_type, *proc = typeStruct->typinput; else *proc = typeStruct->typoutput; + ReleaseSysCache(typeTuple); } /* diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c index f32122173d8..6022dc78519 100644 --- a/src/backend/utils/adt/format_type.c +++ b/src/backend/utils/adt/format_type.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.5 2000/08/26 21:53:41 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.6 2000/11/16 22:30:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -98,9 +98,9 @@ format_type_internal(Oid type_oid, int32 typemod) if (type_oid == InvalidOid) return pstrdup("-"); - tuple = SearchSysCacheTuple(TYPEOID, ObjectIdGetDatum(type_oid), - 0, 0, 0); - + tuple = SearchSysCache(TYPEOID, + ObjectIdGetDatum(type_oid), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) return pstrdup("???"); @@ -108,9 +108,11 @@ format_type_internal(Oid type_oid, int32 typemod) typlen = ((Form_pg_type) GETSTRUCT(tuple))->typlen; if (array_base_type != 0 && typlen < 0) { - tuple = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(array_base_type), - 0, 0, 0); + /* Switch our attention to the array element type */ + ReleaseSysCache(tuple); + tuple = SearchSysCache(TYPEOID, + ObjectIdGetDatum(array_base_type), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) return pstrdup("???[]"); is_array = true; @@ -211,6 +213,8 @@ format_type_internal(Oid type_oid, int32 typemod) if (is_array) buf = psnprintf(strlen(buf) + 3, "%s[]", buf); + ReleaseSysCache(tuple); + return buf; } diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c index 84c4694115d..4a2bb3c4fd6 100644 --- a/src/backend/utils/adt/regproc.c +++ b/src/backend/utils/adt/regproc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.58 2000/07/09 21:30:12 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.59 2000/11/16 22:30:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -55,13 +55,12 @@ regprocin(PG_FUNCTION_ARGS) if (pro_name_or_oid[0] >= '0' && pro_name_or_oid[0] <= '9') { - proctup = SearchSysCacheTuple(PROCOID, - DirectFunctionCall1(oidin, + result = (RegProcedure) + GetSysCacheOid(PROCOID, + DirectFunctionCall1(oidin, CStringGetDatum(pro_name_or_oid)), - 0, 0, 0); - if (HeapTupleIsValid(proctup)) - result = (RegProcedure) proctup->t_data->t_oid; - else + 0, 0, 0); + if (!RegProcedureIsValid(result)) elog(ERROR, "No procedure with oid %s", pro_name_or_oid); } else @@ -176,9 +175,9 @@ regprocout(PG_FUNCTION_ARGS) if (!IsBootstrapProcessingMode()) { - proctup = SearchSysCacheTuple(PROCOID, - ObjectIdGetDatum(proid), - 0, 0, 0); + proctup = SearchSysCache(PROCOID, + ObjectIdGetDatum(proid), + 0, 0, 0); if (HeapTupleIsValid(proctup)) { @@ -186,6 +185,7 @@ regprocout(PG_FUNCTION_ARGS) s = NameStr(((Form_pg_proc) GETSTRUCT(proctup))->proname); StrNCpy(result, s, NAMEDATALEN); + ReleaseSysCache(proctup); } else { diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c index 723adcda35c..5bfea0ff42f 100644 --- a/src/backend/utils/adt/ri_triggers.c +++ b/src/backend/utils/adt/ri_triggers.c @@ -6,7 +6,7 @@ * * 1999 Jan Wieck * - * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.17 2000/09/25 22:34:20 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.18 2000/11/16 22:30:31 tgl Exp $ * * ---------- */ @@ -3300,24 +3300,26 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue) HeapTuple opr_tup; Form_pg_operator opr_struct; - opr_tup = SearchSysCacheTuple(OPERNAME, - PointerGetDatum("="), - ObjectIdGetDatum(typeid), - ObjectIdGetDatum(typeid), - CharGetDatum('b')); - + opr_tup = SearchSysCache(OPERNAME, + PointerGetDatum("="), + ObjectIdGetDatum(typeid), + ObjectIdGetDatum(typeid), + CharGetDatum('b')); if (!HeapTupleIsValid(opr_tup)) elog(ERROR, "ri_AttributesEqual(): cannot find '=' operator " "for type %u", typeid); opr_struct = (Form_pg_operator) GETSTRUCT(opr_tup); entry = (RI_OpreqHashEntry *) hash_search(ri_opreq_cache, - (char *) &typeid, HASH_ENTER, &found); + (char *) &typeid, + HASH_ENTER, + &found); if (entry == NULL) elog(FATAL, "can't insert into RI operator cache"); entry->typeid = typeid; fmgr_info(opr_struct->oprcode, &(entry->oprfmgrinfo)); + ReleaseSysCache(opr_tup); } /* ---------- diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index cc25a5a026a..3cd543b5e68 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -3,7 +3,7 @@ * back to source text * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.68 2000/11/05 00:15:53 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.69 2000/11/16 22:30:31 tgl Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -374,8 +374,9 @@ pg_get_indexdef(PG_FUNCTION_ARGS) * Fetch the pg_index tuple by the Oid of the index * ---------- */ - ht_idx = SearchSysCacheTuple(INDEXRELID, - ObjectIdGetDatum(indexrelid), 0, 0, 0); + ht_idx = SearchSysCache(INDEXRELID, + ObjectIdGetDatum(indexrelid), + 0, 0, 0); if (!HeapTupleIsValid(ht_idx)) elog(ERROR, "syscache lookup for index %u failed", indexrelid); idxrec = (Form_pg_index) GETSTRUCT(ht_idx); @@ -384,8 +385,9 @@ pg_get_indexdef(PG_FUNCTION_ARGS) * Fetch the pg_class tuple of the index relation * ---------- */ - ht_idxrel = SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(idxrec->indexrelid), 0, 0, 0); + ht_idxrel = SearchSysCache(RELOID, + ObjectIdGetDatum(idxrec->indexrelid), + 0, 0, 0); if (!HeapTupleIsValid(ht_idxrel)) elog(ERROR, "syscache lookup for relid %u failed", idxrec->indexrelid); idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel); @@ -394,8 +396,9 @@ pg_get_indexdef(PG_FUNCTION_ARGS) * Fetch the pg_class tuple of the indexed relation * ---------- */ - ht_indrel = SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(idxrec->indrelid), 0, 0, 0); + ht_indrel = SearchSysCache(RELOID, + ObjectIdGetDatum(idxrec->indrelid), + 0, 0, 0); if (!HeapTupleIsValid(ht_indrel)) elog(ERROR, "syscache lookup for relid %u failed", idxrec->indrelid); indrelrec = (Form_pg_class) GETSTRUCT(ht_indrel); @@ -484,12 +487,13 @@ pg_get_indexdef(PG_FUNCTION_ARGS) HeapTuple proctup; Form_pg_proc procStruct; - proctup = SearchSysCacheTuple(PROCOID, - ObjectIdGetDatum(idxrec->indproc), 0, 0, 0); + proctup = SearchSysCache(PROCOID, + ObjectIdGetDatum(idxrec->indproc), + 0, 0, 0); if (!HeapTupleIsValid(proctup)) elog(ERROR, "cache lookup for proc %u failed", idxrec->indproc); - procStruct = (Form_pg_proc) GETSTRUCT(proctup); + appendStringInfo(&buf, "%s(%s) ", quote_identifier(pstrdup(NameStr(procStruct->proname))), keybuf.data); @@ -508,6 +512,7 @@ pg_get_indexdef(PG_FUNCTION_ARGS) appendStringInfo(&buf, "%s", quote_identifier(SPI_getvalue(spi_tup, spi_ttc, spi_fno))); + ReleaseSysCache(proctup); } else /* ---------- @@ -523,15 +528,19 @@ pg_get_indexdef(PG_FUNCTION_ARGS) appendStringInfo(&buf, ")"); /* ---------- - * Create the result in upper executor memory + * Create the result in upper executor memory, and free objects * ---------- */ len = buf.len + VARHDRSZ; indexdef = SPI_palloc(len); VARATT_SIZEP(indexdef) = len; memcpy(VARDATA(indexdef), buf.data, buf.len); + pfree(buf.data); pfree(keybuf.data); + ReleaseSysCache(ht_idx); + ReleaseSysCache(ht_idxrel); + ReleaseSysCache(ht_indrel); /* ---------- * Disconnect from SPI manager @@ -568,13 +577,14 @@ pg_get_userbyid(PG_FUNCTION_ARGS) * Get the pg_shadow entry and print the result * ---------- */ - usertup = SearchSysCacheTuple(SHADOWSYSID, - ObjectIdGetDatum(uid), - 0, 0, 0); + usertup = SearchSysCache(SHADOWSYSID, + ObjectIdGetDatum(uid), + 0, 0, 0); if (HeapTupleIsValid(usertup)) { user_rec = (Form_pg_shadow) GETSTRUCT(usertup); StrNCpy(NameStr(*result), NameStr(user_rec->usename), NAMEDATALEN); + ReleaseSysCache(usertup); } else sprintf(NameStr(*result), "unknown (UID=%d)", uid); @@ -1392,10 +1402,11 @@ get_rule_expr(Node *node, deparse_context *context) HeapTuple tp; Form_pg_operator optup; - tp = SearchSysCacheTuple(OPEROID, - ObjectIdGetDatum(opno), - 0, 0, 0); - Assert(HeapTupleIsValid(tp)); + tp = SearchSysCache(OPEROID, + ObjectIdGetDatum(opno), + 0, 0, 0); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup for operator %u failed", opno); optup = (Form_pg_operator) GETSTRUCT(tp); switch (optup->oprkind) { @@ -1414,6 +1425,7 @@ get_rule_expr(Node *node, deparse_context *context) default: elog(ERROR, "get_rule_expr: bogus oprkind"); } + ReleaseSysCache(tp); } appendStringInfoChar(buf, ')'); break; @@ -1524,9 +1536,9 @@ get_rule_expr(Node *node, deparse_context *context) /* we do NOT parenthesize the arg expression, for now */ get_rule_expr(fselect->arg, context); - typetup = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(exprType(fselect->arg)), - 0, 0, 0); + typetup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(exprType(fselect->arg)), + 0, 0, 0); if (!HeapTupleIsValid(typetup)) elog(ERROR, "cache lookup of type %u failed", exprType(fselect->arg)); @@ -1538,6 +1550,7 @@ get_rule_expr(Node *node, deparse_context *context) fieldname = get_relid_attribute_name(typrelid, fselect->fieldnum); appendStringInfo(buf, ".%s", quote_identifier(fieldname)); + ReleaseSysCache(typetup); } break; @@ -1550,9 +1563,9 @@ get_rule_expr(Node *node, deparse_context *context) appendStringInfoChar(buf, '('); get_rule_expr(relabel->arg, context); - typetup = SearchSysCacheTuple(TYPEOID, + typetup = SearchSysCache(TYPEOID, ObjectIdGetDatum(relabel->resulttype), - 0, 0, 0); + 0, 0, 0); if (!HeapTupleIsValid(typetup)) elog(ERROR, "cache lookup of type %u failed", relabel->resulttype); @@ -1560,6 +1573,7 @@ get_rule_expr(Node *node, deparse_context *context) extval = pstrdup(NameStr(typeStruct->typname)); appendStringInfo(buf, ")::%s", quote_identifier(extval)); pfree(extval); + ReleaseSysCache(typetup); } break; @@ -1616,14 +1630,14 @@ get_func_expr(Expr *expr, deparse_context *context) /* * Get the functions pg_proc tuple */ - proctup = SearchSysCacheTuple(PROCOID, - ObjectIdGetDatum(func->funcid), - 0, 0, 0); + proctup = SearchSysCache(PROCOID, + ObjectIdGetDatum(func->funcid), + 0, 0, 0); if (!HeapTupleIsValid(proctup)) elog(ERROR, "cache lookup for proc %u failed", func->funcid); procStruct = (Form_pg_proc) GETSTRUCT(proctup); - proname = pstrdup(NameStr(procStruct->proname)); + proname = NameStr(procStruct->proname); /* * nullvalue() and nonnullvalue() should get turned into special @@ -1636,6 +1650,7 @@ get_func_expr(Expr *expr, deparse_context *context) appendStringInfoChar(buf, '('); get_rule_expr((Node *) lfirst(expr->args), context); appendStringInfo(buf, " ISNULL)"); + ReleaseSysCache(proctup); return; } if (strcmp(proname, "nonnullvalue") == 0) @@ -1643,6 +1658,7 @@ get_func_expr(Expr *expr, deparse_context *context) appendStringInfoChar(buf, '('); get_rule_expr((Node *) lfirst(expr->args), context); appendStringInfo(buf, " NOTNULL)"); + ReleaseSysCache(proctup); return; } } @@ -1657,8 +1673,9 @@ get_func_expr(Expr *expr, deparse_context *context) /* * Strip off any RelabelType on the input, so we don't print - * redundancies like x::bpchar::char(8). XXX Are there any cases - * where this is a bad idea? + * redundancies like x::bpchar::char(8). + * + * XXX Are there any cases where this is a bad idea? */ if (IsA(arg, RelabelType)) arg = ((RelabelType *) arg)->arg; @@ -1696,6 +1713,8 @@ get_func_expr(Expr *expr, deparse_context *context) } else appendStringInfo(buf, "%s", quote_identifier(proname)); + + ReleaseSysCache(proctup); return; } @@ -1711,6 +1730,8 @@ get_func_expr(Expr *expr, deparse_context *context) get_rule_expr((Node *) lfirst(l), context); } appendStringInfoChar(buf, ')'); + + ReleaseSysCache(proctup); } @@ -1766,9 +1787,9 @@ get_const_expr(Const *constval, deparse_context *context) char *extval; char *valptr; - typetup = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(constval->consttype), - 0, 0, 0); + typetup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(constval->consttype), + 0, 0, 0); if (!HeapTupleIsValid(typetup)) elog(ERROR, "cache lookup of type %u failed", constval->consttype); @@ -1785,6 +1806,7 @@ get_const_expr(Const *constval, deparse_context *context) extval = pstrdup(NameStr(typeStruct->typname)); appendStringInfo(buf, "NULL::%s", quote_identifier(extval)); pfree(extval); + ReleaseSysCache(typetup); return; } @@ -1843,6 +1865,8 @@ get_const_expr(Const *constval, deparse_context *context) pfree(extval); break; } + + ReleaseSysCache(typetup); } @@ -2198,14 +2222,18 @@ get_relation_name(Oid relid) { HeapTuple classtup; Form_pg_class classStruct; + char *result; - classtup = SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(relid), 0, 0, 0); + classtup = SearchSysCache(RELOID, + ObjectIdGetDatum(relid), + 0, 0, 0); if (!HeapTupleIsValid(classtup)) elog(ERROR, "cache lookup of relation %u failed", relid); classStruct = (Form_pg_class) GETSTRUCT(classtup); - return pstrdup(NameStr(classStruct->relname)); + result = pstrdup(NameStr(classStruct->relname)); + ReleaseSysCache(classtup); + return result; } diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 818bc6ab082..63e4d9b46d2 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.81 2000/11/10 09:38:21 inoue Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.82 2000/11/16 22:30:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -324,12 +324,15 @@ scalarltsel(PG_FUNCTION_ARGS) * Get left and right datatypes of the operator so we know what * type the constant is. */ - oprtuple = get_operator_tuple(opid); + oprtuple = SearchSysCache(OPEROID, + ObjectIdGetDatum(opid), + 0, 0, 0); if (!HeapTupleIsValid(oprtuple)) elog(ERROR, "scalarltsel: no tuple for operator %u", opid); ltype = ((Form_pg_operator) GETSTRUCT(oprtuple))->oprleft; rtype = ((Form_pg_operator) GETSTRUCT(oprtuple))->oprright; contype = (flag & SEL_RIGHT) ? rtype : ltype; + ReleaseSysCache(oprtuple); /* Now get info and stats about the attribute */ getattproperties(relid, attno, @@ -482,11 +485,14 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype) * Get left and right datatypes of the operator so we know what * type the attribute is. */ - oprtuple = get_operator_tuple(opid); + oprtuple = SearchSysCache(OPEROID, + ObjectIdGetDatum(opid), + 0, 0, 0); if (!HeapTupleIsValid(oprtuple)) elog(ERROR, "patternsel: no tuple for operator %u", opid); ltype = ((Form_pg_operator) GETSTRUCT(oprtuple))->oprleft; rtype = ((Form_pg_operator) GETSTRUCT(oprtuple))->oprright; + ReleaseSysCache(oprtuple); /* the right-hand const is type text for all supported operators */ Assert(rtype == TEXTOID); @@ -1189,10 +1195,10 @@ getattproperties(Oid relid, AttrNumber attnum, HeapTuple atp; Form_pg_attribute att_tup; - atp = SearchSysCacheTuple(ATTNUM, - ObjectIdGetDatum(relid), - Int16GetDatum(attnum), - 0, 0); + atp = SearchSysCache(ATTNUM, + ObjectIdGetDatum(relid), + Int16GetDatum(attnum), + 0, 0); if (!HeapTupleIsValid(atp)) elog(ERROR, "getattproperties: no attribute tuple %u %d", relid, (int) attnum); @@ -1202,6 +1208,8 @@ getattproperties(Oid relid, AttrNumber attnum, *typlen = att_tup->attlen; *typbyval = att_tup->attbyval; *typmod = att_tup->atttypmod; + + ReleaseSysCache(atp); } /* @@ -1250,11 +1258,10 @@ getattstatistics(Oid relid, * have at hand! (For example, we might have a '>' operator rather * than the '<' operator that will appear in staop.) */ - tuple = SearchSysCacheTupleCopy(STATRELID, - ObjectIdGetDatum(relid), - Int16GetDatum((int16) attnum), - 0, - 0); + tuple = SearchSysCache(STATRELID, + ObjectIdGetDatum(relid), + Int16GetDatum((int16) attnum), + 0, 0); if (!HeapTupleIsValid(tuple)) { /* no such stats entry */ @@ -1267,14 +1274,15 @@ getattstatistics(Oid relid, *commonfrac = ((Form_pg_statistic) GETSTRUCT(tuple))->stacommonfrac; /* Get the type input proc for the column datatype */ - typeTuple = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(typid), - 0, 0, 0); + typeTuple = SearchSysCache(TYPEOID, + ObjectIdGetDatum(typid), + 0, 0, 0); if (!HeapTupleIsValid(typeTuple)) elog(ERROR, "getattstatistics: Cache lookup failed for type %u", typid); fmgr_info(((Form_pg_type) GETSTRUCT(typeTuple))->typinput, &inputproc); typelem = ((Form_pg_type) GETSTRUCT(typeTuple))->typelem; + ReleaseSysCache(typeTuple); /* * Values are variable-length fields, so cannot access as struct @@ -1351,7 +1359,8 @@ getattstatistics(Oid relid, pfree(strval); } } - heap_freetuple(tuple); + + ReleaseSysCache(tuple); return true; } @@ -1966,16 +1975,11 @@ string_lessthan(const char *str1, const char *str2, Oid datatype) static Oid find_operator(const char *opname, Oid datatype) { - HeapTuple optup; - - optup = SearchSysCacheTuple(OPERNAME, - PointerGetDatum(opname), - ObjectIdGetDatum(datatype), - ObjectIdGetDatum(datatype), - CharGetDatum('b')); - if (!HeapTupleIsValid(optup)) - return InvalidOid; - return optup->t_data->t_oid; + return GetSysCacheOid(OPERNAME, + PointerGetDatum(opname), + ObjectIdGetDatum(datatype), + ObjectIdGetDatum(datatype), + CharGetDatum('b')); } /* diff --git a/src/backend/utils/adt/sets.c b/src/backend/utils/adt/sets.c index 9a5f05134cd..6f64847dcab 100644 --- a/src/backend/utils/adt/sets.c +++ b/src/backend/utils/adt/sets.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.33 2000/08/24 03:29:06 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.34 2000/11/16 22:30:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -77,9 +77,11 @@ SetDefine(char *querystr, char *typename) */ CommandCounterIncrement(); - tup = SearchSysCacheTuple(PROCOID, - ObjectIdGetDatum(setoid), - 0, 0, 0); + procrel = heap_openr(ProcedureRelationName, RowExclusiveLock); + + tup = SearchSysCache(PROCOID, + ObjectIdGetDatum(setoid), + 0, 0, 0); if (!HeapTupleIsValid(tup)) elog(ERROR, "SetDefine: unable to define set %s", querystr); @@ -105,25 +107,15 @@ SetDefine(char *querystr, char *typename) replNull[i] = ' '; /* change the pg_proc tuple */ - procrel = heap_openr(ProcedureRelationName, RowExclusiveLock); + newtup = heap_modifytuple(tup, + procrel, + replValue, + replNull, + repl); - tup = SearchSysCacheTuple(PROCOID, - ObjectIdGetDatum(setoid), - 0, 0, 0); - if (HeapTupleIsValid(tup)) - { - newtup = heap_modifytuple(tup, - procrel, - replValue, - replNull, - repl); + heap_update(procrel, &newtup->t_self, newtup, NULL); - heap_update(procrel, &tup->t_self, newtup, NULL); - - setoid = newtup->t_data->t_oid; - } - else - elog(ERROR, "SetDefine: could not find new set oid tuple"); + setoid = newtup->t_data->t_oid; if (RelationGetForm(procrel)->relhasindex) { @@ -133,9 +125,13 @@ SetDefine(char *querystr, char *typename) CatalogIndexInsert(idescs, Num_pg_proc_indices, procrel, newtup); CatalogCloseIndices(Num_pg_proc_indices, idescs); } - heap_close(procrel, RowExclusiveLock); + heap_freetuple(newtup); } + ReleaseSysCache(tup); + + heap_close(procrel, RowExclusiveLock); + return setoid; } diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index 39e05d0fb09..3d8e7d80ba8 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.71 2000/11/10 00:33:10 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.72 2000/11/16 22:30:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -28,7 +28,8 @@ #include "utils/catcache.h" #include "utils/syscache.h" -static void CatCacheRemoveCTup(CatCache *cache, Dlelem *e); + +static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct); static Index CatalogCacheComputeHashIndex(CatCache *cache, ScanKey cur_skey); static Index CatalogCacheComputeTupleHashIndex(CatCache *cache, @@ -388,28 +389,17 @@ CatalogCacheComputeTupleHashIndex(CatCache *cache, * -------------------------------- */ static void -CatCacheRemoveCTup(CatCache *cache, Dlelem *elt) +CatCacheRemoveCTup(CatCache *cache, CatCTup *ct) { - CatCTup *ct; - CatCTup *other_ct; - Dlelem *other_elt; - - if (!elt) /* probably-useless safety check */ - return; - - /* We need to zap both linked-list elements as well as the tuple */ + Assert(ct->refcount == 0); - ct = (CatCTup *) DLE_VAL(elt); - other_elt = ct->ct_node; - other_ct = (CatCTup *) DLE_VAL(other_elt); + /* delink from linked lists */ + DLRemove(&ct->lrulist_elem); + DLRemove(&ct->cache_elem); - heap_freetuple(ct->ct_tup); - - DLRemove(other_elt); - DLFreeElem(other_elt); - pfree(other_ct); - DLRemove(elt); - DLFreeElem(elt); + /* free associated tuple data */ + if (ct->tuple.t_data != NULL) + pfree(ct->tuple.t_data); pfree(ct); --cache->cc_ntup; @@ -425,13 +415,11 @@ CatCacheRemoveCTup(CatCache *cache, Dlelem *elt) * -------------------------------- */ void -CatalogCacheIdInvalidate(int cacheId, /* XXX */ +CatalogCacheIdInvalidate(int cacheId, Index hashIndex, ItemPointer pointer) { CatCache *ccp; - CatCTup *ct; - Dlelem *elt; /* ---------------- * sanity checks @@ -442,54 +430,101 @@ CatalogCacheIdInvalidate(int cacheId, /* XXX */ CACHE1_elog(DEBUG, "CatalogCacheIdInvalidate: called"); /* ---------------- - * inspect every cache that could contain the tuple + * inspect caches to find the proper cache * ---------------- */ for (ccp = Caches; ccp; ccp = ccp->cc_next) { + Dlelem *elt, + *nextelt; + if (cacheId != ccp->id) continue; /* ---------------- * inspect the hash bucket until we find a match or exhaust * ---------------- */ - for (elt = DLGetHead(ccp->cc_cache[hashIndex]); - elt; - elt = DLGetSucc(elt)) + for (elt = DLGetHead(&ccp->cc_cache[hashIndex]); elt; elt = nextelt) { - ct = (CatCTup *) DLE_VAL(elt); - if (ItemPointerEquals(pointer, &ct->ct_tup->t_self)) - break; - } - - /* ---------------- - * if we found a matching tuple, invalidate it. - * ---------------- - */ + CatCTup *ct = (CatCTup *) DLE_VAL(elt); - if (elt) - { - CatCacheRemoveCTup(ccp, elt); + nextelt = DLGetSucc(elt); - CACHE1_elog(DEBUG, "CatalogCacheIdInvalidate: invalidated"); + if (ItemPointerEquals(pointer, &ct->tuple.t_self)) + { + if (ct->refcount > 0) + ct->dead = true; + else + CatCacheRemoveCTup(ccp, ct); + CACHE1_elog(DEBUG, "CatalogCacheIdInvalidate: invalidated"); + /* could be multiple matches, so keep looking! */ + } } - - if (cacheId != InvalidCatalogCacheId) - break; + break; /* need only search this one cache */ } } /* ---------------------------------------------------------------- * public functions * + * AtEOXact_CatCache * ResetSystemCache - * InitSysCache - * SearchSysCache + * InitCatCache + * SearchCatCache + * ReleaseCatCache * RelationInvalidateCatalogCacheTuple * ---------------------------------------------------------------- */ + + +/* -------------------------------- + * AtEOXact_CatCache + * + * Clean up catcaches at end of transaction (either commit or abort) + * + * We scan the caches to reset refcounts to zero. This is of course + * necessary in the abort case, since elog() may have interrupted routines. + * In the commit case, any nonzero counts indicate failure to call + * ReleaseSysCache, so we put out a notice for debugging purposes. + * -------------------------------- + */ +void +AtEOXact_CatCache(bool isCommit) +{ + CatCache *cache; + + for (cache = Caches; cache; cache = cache->cc_next) + { + Dlelem *elt, + *nextelt; + + for (elt = DLGetHead(&cache->cc_lrulist); elt; elt = nextelt) + { + CatCTup *ct = (CatCTup *) DLE_VAL(elt); + + nextelt = DLGetSucc(elt); + + if (ct->refcount != 0) + { + if (isCommit) + elog(NOTICE, "Cache reference leak: cache %s (%d), tuple %u has count %d", + cache->cc_relname, cache->id, + ct->tuple.t_data->t_oid, + ct->refcount); + ct->refcount = 0; + } + + /* Clean up any now-deletable dead entries */ + if (ct->dead) + CatCacheRemoveCTup(cache, ct); + } + } +} + /* -------------------------------- * ResetSystemCache + * + * Reset caches when a shared cache inval event forces it * -------------------------------- */ void @@ -503,34 +538,25 @@ ResetSystemCache(void) * here we purge the contents of all the caches * * for each system cache - * for each hash bucket - * for each tuple in hash bucket - * remove the tuple + * for each tuple + * remove the tuple, or at least mark it dead * ---------------- */ - for (cache = Caches; PointerIsValid(cache); cache = cache->cc_next) + for (cache = Caches; cache; cache = cache->cc_next) { - int hash; + Dlelem *elt, + *nextelt; - for (hash = 0; hash < NCCBUCK; hash += 1) + for (elt = DLGetHead(&cache->cc_lrulist); elt; elt = nextelt) { - Dlelem *elt, - *nextelt; + CatCTup *ct = (CatCTup *) DLE_VAL(elt); - for (elt = DLGetHead(cache->cc_cache[hash]); elt; elt = nextelt) - { - nextelt = DLGetSucc(elt); - CatCacheRemoveCTup(cache, elt); - } - } + nextelt = DLGetSucc(elt); - /* double-check that ntup is now zero */ - if (cache->cc_ntup != 0) - { - elog(NOTICE, - "ResetSystemCache: cache %d has cc_ntup = %d, should be 0", - cache->id, cache->cc_ntup); - cache->cc_ntup = 0; + if (ct->refcount > 0) + ct->dead = true; + else + CatCacheRemoveCTup(cache, ct); } } @@ -572,7 +598,7 @@ SystemCacheRelationFlushed(Oid relId) } /* -------------------------------- - * InitSysCache + * InitCatCache * * This allocates and initializes a cache for a system catalog relation. * Actually, the cache is only partially initialized to avoid opening the @@ -581,18 +607,18 @@ SystemCacheRelationFlushed(Oid relId) * -------------------------------- */ #ifdef CACHEDEBUG -#define InitSysCache_DEBUG1 \ +#define InitCatCache_DEBUG1 \ do { \ - elog(DEBUG, "InitSysCache: rel=%s id=%d nkeys=%d size=%d\n", \ + elog(DEBUG, "InitCatCache: rel=%s id=%d nkeys=%d size=%d\n", \ cp->cc_relname, cp->id, cp->cc_nkeys, cp->cc_size); \ } while(0) #else -#define InitSysCache_DEBUG1 +#define InitCatCache_DEBUG1 #endif CatCache * -InitSysCache(int id, +InitCatCache(int id, char *relname, char *indname, int nkeys, @@ -624,25 +650,9 @@ InitSysCache(int id, * and the LRU tuple list * ---------------- */ - { - - /* - * We can only do this optimization because the number of hash - * buckets never changes. Without it, we call palloc() too much. - * We could move this to dllist.c, but the way we do this is not - * dynamic/portable, so why allow other routines to use it. - */ - Dllist *cache_begin = palloc((NCCBUCK + 1) * sizeof(Dllist)); - - for (i = 0; i <= NCCBUCK; ++i) - { - cp->cc_cache[i] = &cache_begin[i]; - cp->cc_cache[i]->dll_head = 0; - cp->cc_cache[i]->dll_tail = 0; - } - } - - cp->cc_lrulist = DLNewList(); + DLInitList(&cp->cc_lrulist); + for (i = 0; i < NCCBUCK; ++i) + DLInitList(&cp->cc_cache[i]); /* ---------------- * Caches is the pointer to the head of the list of all the @@ -673,7 +683,7 @@ InitSysCache(int id, * information, if appropriate. * ---------------- */ - InitSysCache_DEBUG1; + InitCatCache_DEBUG1; /* ---------------- * back to the old context before we return... @@ -742,14 +752,14 @@ IndexScanOK(CatCache *cache, ScanKey cur_skey) } /* -------------------------------- - * SearchSysCache + * SearchCatCache * * This call searches a system cache for a tuple, opening the relation * if necessary (the first access to a particular cache). * -------------------------------- */ HeapTuple -SearchSysCache(CatCache *cache, +SearchCatCache(CatCache *cache, Datum v1, Datum v2, Datum v3, @@ -757,10 +767,8 @@ SearchSysCache(CatCache *cache, { ScanKeyData cur_skey[4]; Index hash; - CatCTup *ct = NULL; - CatCTup *nct; - CatCTup *nct2; Dlelem *elt; + CatCTup *ct; HeapTuple ntp; Relation relation; MemoryContext oldcxt; @@ -792,48 +800,50 @@ SearchSysCache(CatCache *cache, * scan the hash bucket until we find a match or exhaust our tuples * ---------------- */ - for (elt = DLGetHead(cache->cc_cache[hash]); + for (elt = DLGetHead(&cache->cc_cache[hash]); elt; elt = DLGetSucc(elt)) { bool res; ct = (CatCTup *) DLE_VAL(elt); + + if (ct->dead) + continue; /* ignore dead entries */ + /* ---------------- * see if the cached tuple matches our key. * (should we be worried about time ranges? -cim 10/2/90) * ---------------- */ - HeapKeyTest(ct->ct_tup, + HeapKeyTest(&ct->tuple, cache->cc_tupdesc, cache->cc_nkeys, cur_skey, res); - if (res) - break; - } + if (! res) + continue; - /* ---------------- - * if we found a tuple in the cache, move it to the top of the - * lru list, and return it. We also move it to the front of the - * list for its hashbucket, in order to speed subsequent searches. - * (The most frequently accessed elements in any hashbucket will - * tend to be near the front of the hashbucket's list.) - * ---------------- - */ - if (elt) - { - Dlelem *old_lru_elt = ((CatCTup *) DLE_VAL(elt))->ct_node; + /* ---------------- + * we found a tuple in the cache: bump its refcount, move it to + * the front of the LRU list, and return it. We also move it + * to the front of the list for its hashbucket, in order to speed + * subsequent searches. (The most frequently accessed elements + * in any hashbucket will tend to be near the front of the + * hashbucket's list.) + * ---------------- + */ + ct->refcount++; - DLMoveToFront(old_lru_elt); - DLMoveToFront(elt); + DLMoveToFront(&ct->lrulist_elem); + DLMoveToFront(&ct->cache_elem); #ifdef CACHEDEBUG - CACHE3_elog(DEBUG, "SearchSysCache(%s): found in bucket %d", + CACHE3_elog(DEBUG, "SearchCatCache(%s): found in bucket %d", cache->cc_relname, hash); #endif /* CACHEDEBUG */ - return ct->ct_tup; + return &ct->tuple; } /* ---------------- @@ -864,7 +874,7 @@ SearchSysCache(CatCache *cache, * if it's safe to do so, use the index. Else do a heap scan. * ---------------- */ - ntp = NULL; + ct = NULL; if ((RelationGetForm(relation))->relhasindex && !IsIgnoringSystemIndexes() && @@ -876,7 +886,7 @@ SearchSysCache(CatCache *cache, HeapTupleData tuple; Buffer buffer; - CACHE2_elog(DEBUG, "SearchSysCache(%s): performing index scan", + CACHE2_elog(DEBUG, "SearchCatCache(%s): performing index scan", cache->cc_relname); idesc = index_openr(cache->cc_indname); @@ -892,7 +902,8 @@ SearchSysCache(CatCache *cache, { /* Copy tuple into our context */ oldcxt = MemoryContextSwitchTo(CacheMemoryContext); - ntp = heap_copytuple(&tuple); + ct = (CatCTup *) palloc(sizeof(CatCTup)); + heap_copytuple_with_tuple(&tuple, &ct->tuple); MemoryContextSwitchTo(oldcxt); ReleaseBuffer(buffer); break; @@ -906,7 +917,7 @@ SearchSysCache(CatCache *cache, HeapScanDesc sd; int i; - CACHE2_elog(DEBUG, "SearchSysCache(%s): performing heap scan", + CACHE2_elog(DEBUG, "SearchCatCache(%s): performing heap scan", cache->cc_relname); /* @@ -925,7 +936,8 @@ SearchSysCache(CatCache *cache, { /* Copy tuple into our context */ oldcxt = MemoryContextSwitchTo(CacheMemoryContext); - ntp = heap_copytuple(ntp); + ct = (CatCTup *) palloc(sizeof(CatCTup)); + heap_copytuple_with_tuple(ntp, &ct->tuple); MemoryContextSwitchTo(oldcxt); /* We should not free the result of heap_getnext... */ } @@ -934,77 +946,102 @@ SearchSysCache(CatCache *cache, } /* ---------------- - * scan is complete. if tup is valid, we can add it to the cache. - * note we have already copied it into the cache memory context. + * close the relation * ---------------- */ - if (HeapTupleIsValid(ntp)) - { - /* ---------------- - * allocate a new cache tuple holder, store the pointer - * to the heap tuple there and initialize the list pointers. - * ---------------- - */ - Dlelem *lru_elt; - - CACHE1_elog(DEBUG, "SearchSysCache: found tuple"); + heap_close(relation, AccessShareLock); - oldcxt = MemoryContextSwitchTo(CacheMemoryContext); + /* ---------------- + * scan is complete. if tup was found, we can add it to the cache. + * ---------------- + */ + if (ct == NULL) + return NULL; - /* - * this is a little cumbersome here because we want the Dlelem's - * in both doubly linked lists to point to one another. That makes - * it easier to remove something from both the cache bucket and - * the lru list at the same time - */ - nct = (CatCTup *) palloc(sizeof(CatCTup)); - nct->ct_tup = ntp; - elt = DLNewElem(nct); - nct2 = (CatCTup *) palloc(sizeof(CatCTup)); - nct2->ct_tup = ntp; - lru_elt = DLNewElem(nct2); - nct2->ct_node = elt; - nct->ct_node = lru_elt; + /* ---------------- + * Finish initializing the CatCTup header, and add it to the + * linked lists. + * ---------------- + */ + CACHE1_elog(DEBUG, "SearchCatCache: found tuple"); - DLAddHead(cache->cc_lrulist, lru_elt); - DLAddHead(cache->cc_cache[hash], elt); + ct->ct_magic = CT_MAGIC; + DLInitElem(&ct->lrulist_elem, (void *) ct); + DLInitElem(&ct->cache_elem, (void *) ct); + ct->refcount = 1; /* count this first reference */ + ct->dead = false; - MemoryContextSwitchTo(oldcxt); + DLAddHead(&cache->cc_lrulist, &ct->lrulist_elem); + DLAddHead(&cache->cc_cache[hash], &ct->cache_elem); - /* ---------------- - * If we've exceeded the desired size of this cache, - * throw away the least recently used entry. - * ---------------- - */ - if (++cache->cc_ntup > cache->cc_maxtup) + /* ---------------- + * If we've exceeded the desired size of this cache, + * try to throw away the least recently used entry. + * ---------------- + */ + if (++cache->cc_ntup > cache->cc_maxtup) + { + for (elt = DLGetTail(&cache->cc_lrulist); + elt; + elt = DLGetPred(elt)) { - CatCTup *ct; + CatCTup *oldct = (CatCTup *) DLE_VAL(elt); - elt = DLGetTail(cache->cc_lrulist); - ct = (CatCTup *) DLE_VAL(elt); - - if (ct != nct) /* shouldn't be possible, but be safe... */ + if (oldct->refcount == 0) { - CACHE2_elog(DEBUG, "SearchSysCache(%s): Overflow, LRU removal", + CACHE2_elog(DEBUG, "SearchCatCache(%s): Overflow, LRU removal", cache->cc_relname); - - CatCacheRemoveCTup(cache, elt); + CatCacheRemoveCTup(cache, oldct); + break; } } - - CACHE4_elog(DEBUG, "SearchSysCache(%s): Contains %d/%d tuples", - cache->cc_relname, cache->cc_ntup, cache->cc_maxtup); - CACHE3_elog(DEBUG, "SearchSysCache(%s): put in bucket %d", - cache->cc_relname, hash); } - /* ---------------- - * close the relation and return the tuple we found (or NULL) - * ---------------- - */ - heap_close(relation, AccessShareLock); + CACHE4_elog(DEBUG, "SearchCatCache(%s): Contains %d/%d tuples", + cache->cc_relname, cache->cc_ntup, cache->cc_maxtup); + CACHE3_elog(DEBUG, "SearchCatCache(%s): put in bucket %d", + cache->cc_relname, hash); + + return &ct->tuple; +} - return ntp; +/* -------------------------------- + * ReleaseCatCache() + * + * Decrement the reference count of a catcache entry (releasing the + * hold grabbed by a successful SearchCatCache). + * + * NOTE: if compiled with -DCATCACHE_FORCE_RELEASE then catcache entries + * will be freed as soon as their refcount goes to zero. In combination + * with aset.c's CLOBBER_FREED_MEMORY option, this provides a good test + * to catch references to already-released catcache entries. + * -------------------------------- + */ +void +ReleaseCatCache(HeapTuple tuple) +{ + CatCTup *ct = (CatCTup *) (((char *) tuple) - + offsetof(CatCTup, tuple)); + + /* Safety checks to ensure we were handed a cache entry */ + Assert(ct->ct_magic == CT_MAGIC); + Assert(ct->refcount > 0); + + ct->refcount--; + + if (ct->refcount == 0 +#ifndef CATCACHE_FORCE_RELEASE + && ct->dead +#endif + ) + { + /* We can find the associated cache using the dllist pointers */ + Dllist *lru = DLGetListHdr(&ct->lrulist_elem); + CatCache *cache = (CatCache *) (((char *) lru) - + offsetof(CatCache, cc_lrulist)); + + CatCacheRemoveCTup(cache, ct); + } } /* -------------------------------- diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index b9bd9f8b9e9..e07445837a5 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.46 2000/10/05 19:48:29 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.47 2000/11/16 22:30:33 tgl Exp $ * * NOTES * Eventually, the index information should go through here, too. @@ -32,14 +32,11 @@ bool op_class(Oid opno, Oid opclass, Oid amopid) { - if (HeapTupleIsValid(SearchSysCacheTuple(AMOPOPID, - ObjectIdGetDatum(opclass), - ObjectIdGetDatum(opno), - ObjectIdGetDatum(amopid), - 0))) - return true; - else - return false; + return SearchSysCacheExists(AMOPOPID, + ObjectIdGetDatum(opclass), + ObjectIdGetDatum(opno), + ObjectIdGetDatum(amopid), + 0); } /* ---------- ATTRIBUTE CACHES ---------- */ @@ -49,21 +46,26 @@ op_class(Oid opno, Oid opclass, Oid amopid) * * Given the relation id and the attribute number, * return the "attname" field from the attribute relation. + * + * Note: returns a palloc'd copy of the string, or NULL if no such operator. */ char * get_attname(Oid relid, AttrNumber attnum) { HeapTuple tp; - tp = SearchSysCacheTuple(ATTNUM, - ObjectIdGetDatum(relid), - Int16GetDatum(attnum), - 0, 0); + tp = SearchSysCache(ATTNUM, + ObjectIdGetDatum(relid), + Int16GetDatum(attnum), + 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp); + char *result; - return pstrdup(NameStr(att_tup->attname)); + result = pstrdup(NameStr(att_tup->attname)); + ReleaseSysCache(tp); + return result; } else return NULL; @@ -80,15 +82,18 @@ get_attnum(Oid relid, char *attname) { HeapTuple tp; - tp = SearchSysCacheTuple(ATTNAME, - ObjectIdGetDatum(relid), - PointerGetDatum(attname), - 0, 0); + tp = SearchSysCache(ATTNAME, + ObjectIdGetDatum(relid), + PointerGetDatum(attname), + 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp); + AttrNumber result; - return att_tup->attnum; + result = att_tup->attnum; + ReleaseSysCache(tp); + return result; } else return InvalidAttrNumber; @@ -105,15 +110,18 @@ get_atttype(Oid relid, AttrNumber attnum) { HeapTuple tp; - tp = SearchSysCacheTuple(ATTNUM, - ObjectIdGetDatum(relid), - Int16GetDatum(attnum), - 0, 0); + tp = SearchSysCache(ATTNUM, + ObjectIdGetDatum(relid), + Int16GetDatum(attnum), + 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp); + Oid result; - return att_tup->atttypid; + result = att_tup->atttypid; + ReleaseSysCache(tp); + return result; } else return InvalidOid; @@ -128,15 +136,18 @@ get_attisset(Oid relid, char *attname) { HeapTuple tp; - tp = SearchSysCacheTuple(ATTNAME, - ObjectIdGetDatum(relid), - PointerGetDatum(attname), - 0, 0); + tp = SearchSysCache(ATTNAME, + ObjectIdGetDatum(relid), + PointerGetDatum(attname), + 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp); + bool result; - return att_tup->attisset; + result = att_tup->attisset; + ReleaseSysCache(tp); + return result; } else return false; @@ -153,15 +164,18 @@ get_atttypmod(Oid relid, AttrNumber attnum) { HeapTuple tp; - tp = SearchSysCacheTuple(ATTNUM, - ObjectIdGetDatum(relid), - Int16GetDatum(attnum), - 0, 0); + tp = SearchSysCache(ATTNUM, + ObjectIdGetDatum(relid), + Int16GetDatum(attnum), + 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp); + int32 result; - return att_tup->atttypmod; + result = att_tup->atttypmod; + ReleaseSysCache(tp); + return result; } else return -1; @@ -185,12 +199,13 @@ get_attdispersion(Oid relid, AttrNumber attnum, double min_estimate) HeapTuple atp; Form_pg_attribute att_tup; double dispersion; + Oid atttypid; int32 ntuples; - atp = SearchSysCacheTuple(ATTNUM, - ObjectIdGetDatum(relid), - Int16GetDatum(attnum), - 0, 0); + atp = SearchSysCache(ATTNUM, + ObjectIdGetDatum(relid), + Int16GetDatum(attnum), + 0, 0); if (!HeapTupleIsValid(atp)) { /* this should not happen */ @@ -198,9 +213,14 @@ get_attdispersion(Oid relid, AttrNumber attnum, double min_estimate) relid, attnum); return min_estimate; } + att_tup = (Form_pg_attribute) GETSTRUCT(atp); dispersion = att_tup->attdispersion; + atttypid = att_tup->atttypid; + + ReleaseSysCache(atp); + if (dispersion > 0.0) return dispersion; /* we have a specific estimate from VACUUM */ @@ -211,7 +231,7 @@ get_attdispersion(Oid relid, AttrNumber attnum, double min_estimate) * * Are there any other cases we should wire in special estimates for? */ - if (att_tup->atttypid == BOOLOID) + if (atttypid == BOOLOID) return 0.5; /* @@ -219,9 +239,9 @@ get_attdispersion(Oid relid, AttrNumber attnum, double min_estimate) * 1/numtuples). Either way, we need the relation size. */ - atp = SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(relid), - 0, 0, 0); + atp = SearchSysCache(RELOID, + ObjectIdGetDatum(relid), + 0, 0, 0); if (!HeapTupleIsValid(atp)) { /* this should not happen */ @@ -231,6 +251,8 @@ get_attdispersion(Oid relid, AttrNumber attnum, double min_estimate) ntuples = ((Form_pg_class) GETSTRUCT(atp))->reltuples; + ReleaseSysCache(atp); + if (ntuples == 0) return min_estimate; /* no data available */ @@ -277,14 +299,17 @@ get_opcode(Oid opno) { HeapTuple tp; - tp = SearchSysCacheTuple(OPEROID, - ObjectIdGetDatum(opno), - 0, 0, 0); + tp = SearchSysCache(OPEROID, + ObjectIdGetDatum(opno), + 0, 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp); + RegProcedure result; - return optup->oprcode; + result = optup->oprcode; + ReleaseSysCache(tp); + return result; } else return (RegProcedure) InvalidOid; @@ -301,14 +326,17 @@ get_opname(Oid opno) { HeapTuple tp; - tp = SearchSysCacheTuple(OPEROID, - ObjectIdGetDatum(opno), - 0, 0, 0); + tp = SearchSysCache(OPEROID, + ObjectIdGetDatum(opno), + 0, 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp); + char *result; - return pstrdup(NameStr(optup->oprname)); + result = pstrdup(NameStr(optup->oprname)); + ReleaseSysCache(tp); + return result; } else return NULL; @@ -324,10 +352,11 @@ bool op_mergejoinable(Oid opno, Oid ltype, Oid rtype, Oid *leftOp, Oid *rightOp) { HeapTuple tp; + bool result = false; - tp = SearchSysCacheTuple(OPEROID, - ObjectIdGetDatum(opno), - 0, 0, 0); + tp = SearchSysCache(OPEROID, + ObjectIdGetDatum(opno), + 0, 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp); @@ -339,10 +368,11 @@ op_mergejoinable(Oid opno, Oid ltype, Oid rtype, Oid *leftOp, Oid *rightOp) { *leftOp = optup->oprlsortop; *rightOp = optup->oprrsortop; - return true; + result = true; } + ReleaseSysCache(tp); } - return false; + return result; } /* @@ -355,10 +385,11 @@ Oid op_hashjoinable(Oid opno, Oid ltype, Oid rtype) { HeapTuple tp; + Oid result = InvalidOid; - tp = SearchSysCacheTuple(OPEROID, - ObjectIdGetDatum(opno), - 0, 0, 0); + tp = SearchSysCache(OPEROID, + ObjectIdGetDatum(opno), + 0, 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp); @@ -366,9 +397,10 @@ op_hashjoinable(Oid opno, Oid ltype, Oid rtype) if (optup->oprcanhash && optup->oprleft == ltype && optup->oprright == rtype) - return opno; + result = opno; + ReleaseSysCache(tp); } - return InvalidOid; + return result; } /* @@ -387,14 +419,6 @@ op_iscachable(Oid opno) return func_iscachable((Oid) funcid); } -HeapTuple -get_operator_tuple(Oid opno) -{ - return SearchSysCacheTuple(OPEROID, - ObjectIdGetDatum(opno), - 0, 0, 0); -} - /* * get_commutator * @@ -405,14 +429,17 @@ get_commutator(Oid opno) { HeapTuple tp; - tp = SearchSysCacheTuple(OPEROID, - ObjectIdGetDatum(opno), - 0, 0, 0); + tp = SearchSysCache(OPEROID, + ObjectIdGetDatum(opno), + 0, 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp); + Oid result; - return optup->oprcom; + result = optup->oprcom; + ReleaseSysCache(tp); + return result; } else return InvalidOid; @@ -428,14 +455,17 @@ get_negator(Oid opno) { HeapTuple tp; - tp = SearchSysCacheTuple(OPEROID, - ObjectIdGetDatum(opno), - 0, 0, 0); + tp = SearchSysCache(OPEROID, + ObjectIdGetDatum(opno), + 0, 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp); + Oid result; - return optup->oprnegate; + result = optup->oprnegate; + ReleaseSysCache(tp); + return result; } else return InvalidOid; @@ -451,14 +481,17 @@ get_oprrest(Oid opno) { HeapTuple tp; - tp = SearchSysCacheTuple(OPEROID, - ObjectIdGetDatum(opno), - 0, 0, 0); + tp = SearchSysCache(OPEROID, + ObjectIdGetDatum(opno), + 0, 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp); + RegProcedure result; - return optup->oprrest; + result = optup->oprrest; + ReleaseSysCache(tp); + return result; } else return (RegProcedure) InvalidOid; @@ -474,14 +507,17 @@ get_oprjoin(Oid opno) { HeapTuple tp; - tp = SearchSysCacheTuple(OPEROID, - ObjectIdGetDatum(opno), - 0, 0, 0); + tp = SearchSysCache(OPEROID, + ObjectIdGetDatum(opno), + 0, 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tp); + RegProcedure result; - return optup->oprjoin; + result = optup->oprjoin; + ReleaseSysCache(tp); + return result; } else return (RegProcedure) InvalidOid; @@ -496,15 +532,18 @@ get_oprjoin(Oid opno) Oid get_func_rettype(Oid funcid) { - HeapTuple func_tuple; + HeapTuple tp; + Oid result; - func_tuple = SearchSysCacheTuple(PROCOID, - ObjectIdGetDatum(funcid), - 0, 0, 0); - if (!HeapTupleIsValid(func_tuple)) + tp = SearchSysCache(PROCOID, + ObjectIdGetDatum(funcid), + 0, 0, 0); + if (!HeapTupleIsValid(tp)) elog(ERROR, "Function OID %u does not exist", funcid); - return ((Form_pg_proc) GETSTRUCT(func_tuple))->prorettype; + result = ((Form_pg_proc) GETSTRUCT(tp))->prorettype; + ReleaseSysCache(tp); + return result; } /* @@ -514,15 +553,18 @@ get_func_rettype(Oid funcid) bool func_iscachable(Oid funcid) { - HeapTuple func_tuple; + HeapTuple tp; + bool result; - func_tuple = SearchSysCacheTuple(PROCOID, - ObjectIdGetDatum(funcid), - 0, 0, 0); - if (!HeapTupleIsValid(func_tuple)) + tp = SearchSysCache(PROCOID, + ObjectIdGetDatum(funcid), + 0, 0, 0); + if (!HeapTupleIsValid(tp)) elog(ERROR, "Function OID %u does not exist", funcid); - return ((Form_pg_proc) GETSTRUCT(func_tuple))->proiscachable; + result = ((Form_pg_proc) GETSTRUCT(tp))->proiscachable; + ReleaseSysCache(tp); + return result; } /* ---------- RELATION CACHE ---------- */ @@ -538,14 +580,17 @@ get_relnatts(Oid relid) { HeapTuple tp; - tp = SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(relid), - 0, 0, 0); + tp = SearchSysCache(RELOID, + ObjectIdGetDatum(relid), + 0, 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp); + int result; - return reltup->relnatts; + result = reltup->relnatts; + ReleaseSysCache(tp); + return result; } else return InvalidAttrNumber; @@ -556,20 +601,25 @@ get_relnatts(Oid relid) * get_rel_name * * Returns the name of a given relation. + * + * Note: returns a palloc'd copy of the string, or NULL if no such operator. */ char * get_rel_name(Oid relid) { HeapTuple tp; - tp = SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(relid), - 0, 0, 0); + tp = SearchSysCache(RELOID, + ObjectIdGetDatum(relid), + 0, 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_class reltup = (Form_pg_class) GETSTRUCT(tp); + char *result; - return pstrdup(NameStr(reltup->relname)); + result = pstrdup(NameStr(reltup->relname)); + ReleaseSysCache(tp); + return result; } else return NULL; @@ -587,14 +637,17 @@ get_typlen(Oid typid) { HeapTuple tp; - tp = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(typid), - 0, 0, 0); + tp = SearchSysCache(TYPEOID, + ObjectIdGetDatum(typid), + 0, 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp); + int16 result; - return typtup->typlen; + result = typtup->typlen; + ReleaseSysCache(tp); + return result; } else return 0; @@ -611,33 +664,66 @@ get_typbyval(Oid typid) { HeapTuple tp; - tp = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(typid), - 0, 0, 0); + tp = SearchSysCache(TYPEOID, + ObjectIdGetDatum(typid), + 0, 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp); + bool result; - return typtup->typbyval; + result = typtup->typbyval; + ReleaseSysCache(tp); + return result; } else return false; } +/* + * get_typlenbyval + * + * A two-fer: given the type OID, return both typlen and typbyval. + * + * Since both pieces of info are needed to know how to copy a Datum, + * many places need both. Might as well get them with one cache lookup + * instead of two. Also, this routine raises an error instead of + * returning a bogus value when given a bad type OID. + */ +void +get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval) +{ + HeapTuple tp; + Form_pg_type typtup; + + tp = SearchSysCache(TYPEOID, + ObjectIdGetDatum(typid), + 0, 0, 0); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for type %u", typid); + typtup = (Form_pg_type) GETSTRUCT(tp); + *typlen = typtup->typlen; + *typbyval = typtup->typbyval; + ReleaseSysCache(tp); +} + #ifdef NOT_USED char get_typalign(Oid typid) { HeapTuple tp; - tp = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(typid), - 0, 0, 0); + tp = SearchSysCache(TYPEOID, + ObjectIdGetDatum(typid), + 0, 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp); + char result; - return typtup->typalign; + result = typtup->typalign; + ReleaseSysCache(tp); + return result; } else return 'i'; @@ -666,9 +752,9 @@ get_typdefault(Oid typid) bool typByVal; Datum returnValue; - typeTuple = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(typid), - 0, 0, 0); + typeTuple = SearchSysCache(TYPEOID, + ObjectIdGetDatum(typid), + 0, 0, 0); if (!HeapTupleIsValid(typeTuple)) elog(ERROR, "get_typdefault: failed to lookup type %u", typid); @@ -679,13 +765,17 @@ get_typdefault(Oid typid) * 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); + typDefault = (struct varlena *) + DatumGetPointer(SysCacheGetAttr(TYPEOID, + typeTuple, + Anum_pg_type_typdefault, + &isNull)); if (isNull) + { + ReleaseSysCache(typeTuple); return PointerGetDatum(NULL); + } /* * Otherwise, extract/copy the value. @@ -748,6 +838,8 @@ get_typdefault(Oid typid) } } + ReleaseSysCache(typeTuple); + return returnValue; } @@ -764,14 +856,17 @@ get_typtype(Oid typid) { HeapTuple tp; - tp = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(typid), - 0, 0, 0); + tp = SearchSysCache(TYPEOID, + ObjectIdGetDatum(typid), + 0, 0, 0); if (HeapTupleIsValid(tp)) { Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp); + char result; - return typtup->typtype; + result = typtup->typtype; + ReleaseSysCache(tp); + return result; } else return '\0'; diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index 7f35f192089..bb9a55b869a 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.56 2000/11/10 00:33:10 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.57 2000/11/16 22:30:33 tgl Exp $ * * NOTES * These routines allow the parser/planner/executor to perform @@ -343,7 +343,7 @@ static struct cachedesc cacheinfo[] = { }; static CatCache *SysCache[lengthof(cacheinfo)]; -static int32 SysCacheSize = lengthof(cacheinfo); +static int SysCacheSize = lengthof(cacheinfo); static bool CacheInitialized = false; @@ -355,98 +355,67 @@ IsCacheInitialized(void) /* - * zerocaches + * InitCatalogCache - initialize the caches * - * Make sure the SysCache structure is zero'd. + * Note that no database access is done here; we only allocate memory + * and initialize the cache structure. Interrogation of the database + * to complete initialization of a cache happens only upon first use + * of that cache. */ void -zerocaches() +InitCatalogCache(void) { - MemSet((char *) SysCache, 0, SysCacheSize * sizeof(CatCache *)); -} + int cacheId; + Assert(!CacheInitialized); -/* - * InitCatalogCache - initialize the caches - */ -void -InitCatalogCache() -{ - int cacheId; /* XXX type */ + MemSet((char *) SysCache, 0, sizeof(SysCache)); - if (!AMI_OVERRIDE) + for (cacheId = 0; cacheId < SysCacheSize; cacheId++) { - for (cacheId = 0; cacheId < SysCacheSize; cacheId += 1) - { - Assert(!PointerIsValid(SysCache[cacheId])); - - SysCache[cacheId] = InitSysCache(cacheId, - cacheinfo[cacheId].name, - cacheinfo[cacheId].indname, - cacheinfo[cacheId].nkeys, - cacheinfo[cacheId].key); - if (!PointerIsValid(SysCache[cacheId])) - { - elog(ERROR, - "InitCatalogCache: Can't init cache %s (%d)", - cacheinfo[cacheId].name, - cacheId); - } - - } + SysCache[cacheId] = InitCatCache(cacheId, + cacheinfo[cacheId].name, + cacheinfo[cacheId].indname, + cacheinfo[cacheId].nkeys, + cacheinfo[cacheId].key); + if (!PointerIsValid(SysCache[cacheId])) + elog(ERROR, "InitCatalogCache: Can't init cache %s (%d)", + cacheinfo[cacheId].name, cacheId); } CacheInitialized = true; } /* - * SearchSysCacheTuple + * SearchSysCache * - * A layer on top of SearchSysCache that does the initialization and + * A layer on top of SearchCatCache 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. - * - * CAUTION: The tuple that is returned must NOT be freed by the caller! + * The tuple is the 'cache' copy and must NOT be modified! * - * CAUTION: The returned tuple may be flushed from the cache during - * subsequent cache lookup operations, or by shared cache invalidation. - * Callers should not expect the pointer to remain valid for long. + * When the caller is done using the tuple, call ReleaseSysCache() + * to release the reference count grabbed by SearchSysCache(). If this + * is not done, the tuple will remain locked in cache until end of + * transaction, which is tolerable but not desirable. * - * XXX we ought to have some kind of referencecount mechanism for - * cache entries, to ensure entries aren't deleted while in use. + * CAUTION: The tuple that is returned must NOT be freed by the caller! */ HeapTuple -SearchSysCacheTuple(int cacheId,/* cache selection code */ - Datum key1, - Datum key2, - Datum key3, - Datum key4) +SearchSysCache(int cacheId, + Datum key1, + Datum key2, + Datum key3, + Datum key4) { - HeapTuple tp; - if (cacheId < 0 || cacheId >= SysCacheSize) { - elog(ERROR, "SearchSysCacheTuple: Bad cache id %d", cacheId); + elog(ERROR, "SearchSysCache: Bad cache id %d", cacheId); return (HeapTuple) NULL; } - Assert(AMI_OVERRIDE || PointerIsValid(SysCache[cacheId])); - - if (!PointerIsValid(SysCache[cacheId])) - { - SysCache[cacheId] = InitSysCache(cacheId, - cacheinfo[cacheId].name, - cacheinfo[cacheId].indname, - cacheinfo[cacheId].nkeys, - cacheinfo[cacheId].key); - if (!PointerIsValid(SysCache[cacheId])) - elog(ERROR, - "InitCatalogCache: Can't init cache %s(%d)", - cacheinfo[cacheId].name, - cacheId); - } + Assert(PointerIsValid(SysCache[cacheId])); /* * If someone tries to look up a relname, translate temp relation @@ -464,51 +433,75 @@ SearchSysCacheTuple(int cacheId,/* cache selection code */ key1 = CStringGetDatum(nontemp_relname); } - 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; + return SearchCatCache(SysCache[cacheId], key1, key2, key3, key4); } +/* + * ReleaseSysCache + * Release previously grabbed reference count on a tuple + */ +void +ReleaseSysCache(HeapTuple tuple) +{ + ReleaseCatCache(tuple); +} /* - * SearchSysCacheTupleCopy + * SearchSysCacheCopy * - * This is like SearchSysCacheTuple, except it returns a palloc'd copy of - * the tuple. The caller should heap_freetuple() the returned copy when - * done with it. This routine should be used when the caller intends to - * continue to access the tuple for more than a very short period of time. + * A convenience routine that does SearchSysCache and (if successful) + * returns a modifiable copy of the syscache entry. The original + * syscache entry is released before returning. The caller should + * heap_freetuple() the result when done with it. */ HeapTuple -SearchSysCacheTupleCopy(int cacheId, /* cache selection code */ - Datum key1, - Datum key2, - Datum key3, - Datum key4) +SearchSysCacheCopy(int cacheId, + 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 */ + HeapTuple tuple, + newtuple; + + tuple = SearchSysCache(cacheId, key1, key2, key3, key4); + if (!HeapTupleIsValid(tuple)) + return tuple; + newtuple = heap_copytuple(tuple); + ReleaseSysCache(tuple); + return newtuple; } +/* + * GetSysCacheOid + * + * A convenience routine that does SearchSysCache and returns the OID + * of the found tuple, or InvalidOid if no tuple could be found. + * No lock is retained on the syscache entry. + */ +Oid +GetSysCacheOid(int cacheId, + Datum key1, + Datum key2, + Datum key3, + Datum key4) +{ + HeapTuple tuple; + Oid result; + + tuple = SearchSysCache(cacheId, key1, key2, key3, key4); + if (!HeapTupleIsValid(tuple)) + return InvalidOid; + result = tuple->t_data->t_oid; + ReleaseSysCache(tuple); + return result; +} /* * SysCacheGetAttr * - * Given a tuple previously fetched by SearchSysCacheTuple() or - * SearchSysCacheTupleCopy(), extract a specific attribute. + * Given a tuple previously fetched by SearchSysCache(), + * extract a specific attribute. * * This is equivalent to using heap_getattr() on a tuple fetched * from a non-cached relation. Usually, this is only used for attributes diff --git a/src/backend/utils/cache/temprel.c b/src/backend/utils/cache/temprel.c index 31591663cee..0134b47a0f9 100644 --- a/src/backend/utils/cache/temprel.c +++ b/src/backend/utils/cache/temprel.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/temprel.c,v 1.30 2000/11/08 22:10:01 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/temprel.c,v 1.31 2000/11/16 22:30:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -34,7 +34,6 @@ #include "catalog/heap.h" #include "catalog/index.h" #include "miscadmin.h" -#include "utils/catcache.h" #include "utils/temprel.h" diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c index 3913dddeec2..2dfddebd0a8 100644 --- a/src/backend/utils/fmgr/dfmgr.c +++ b/src/backend/utils/fmgr/dfmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.44 2000/07/05 23:11:40 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.45 2000/11/16 22:30:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -59,9 +59,9 @@ fmgr_dynamic(Oid functionId) PGFunction user_fn; bool isnull; - procedureTuple = SearchSysCacheTuple(PROCOID, - ObjectIdGetDatum(functionId), - 0, 0, 0); + procedureTuple = SearchSysCache(PROCOID, + ObjectIdGetDatum(functionId), + 0, 0, 0); if (!HeapTupleIsValid(procedureTuple)) elog(ERROR, "fmgr_dynamic: function %u: cache lookup failed", functionId); @@ -88,6 +88,8 @@ fmgr_dynamic(Oid functionId) pfree(prosrcstring); pfree(probinstring); + ReleaseSysCache(procedureTuple); + return user_fn; } diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c index c7fbf251f9d..5287615eea0 100644 --- a/src/backend/utils/fmgr/fmgr.c +++ b/src/backend/utils/fmgr/fmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.46 2000/08/24 03:29:07 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.47 2000/11/16 22:30:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -134,9 +134,9 @@ fmgr_info(Oid functionId, FmgrInfo *finfo) } /* Otherwise we need the pg_proc entry */ - procedureTuple = SearchSysCacheTuple(PROCOID, - ObjectIdGetDatum(functionId), - 0, 0, 0); + procedureTuple = SearchSysCache(PROCOID, + ObjectIdGetDatum(functionId), + 0, 0, 0); if (!HeapTupleIsValid(procedureTuple)) elog(ERROR, "fmgr_info: function %u: cache lookup failed", functionId); @@ -149,6 +149,7 @@ fmgr_info(Oid functionId, FmgrInfo *finfo) if (!procedureStruct->proistrusted) { finfo->fn_addr = fmgr_untrusted; + ReleaseSysCache(procedureTuple); return; } @@ -202,14 +203,12 @@ fmgr_info(Oid functionId, FmgrInfo *finfo) /* * Might be a created procedural language; try to look it up. */ - languageTuple = SearchSysCacheTuple(LANGOID, - ObjectIdGetDatum(language), - 0, 0, 0); + languageTuple = SearchSysCache(LANGOID, + ObjectIdGetDatum(language), + 0, 0, 0); if (!HeapTupleIsValid(languageTuple)) - { elog(ERROR, "fmgr_info: cache lookup for language %u failed", language); - } languageStruct = (Form_pg_language) GETSTRUCT(languageTuple); if (languageStruct->lanispl) { @@ -231,8 +230,11 @@ fmgr_info(Oid functionId, FmgrInfo *finfo) elog(ERROR, "fmgr_info: function %u: unsupported language %u", functionId, language); } + ReleaseSysCache(languageTuple); break; } + + ReleaseSysCache(procedureTuple); } diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index 026f2cc8114..ec223157c4b 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.56 2000/11/04 12:43:24 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.57 2000/11/16 22:30:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -340,12 +340,15 @@ SetSessionUserIdFromUserName(const char *username) */ AssertState(!IsBootstrapProcessingMode()); - userTup = SearchSysCacheTuple(SHADOWNAME, - PointerGetDatum(username), - 0, 0, 0); + userTup = SearchSysCache(SHADOWNAME, + PointerGetDatum(username), + 0, 0, 0); if (!HeapTupleIsValid(userTup)) elog(FATAL, "user \"%s\" does not exist", username); + SetSessionUserId( ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid ); + + ReleaseSysCache(userTup); } @@ -355,13 +358,19 @@ SetSessionUserIdFromUserName(const char *username) char * GetUserName(Oid userid) { - HeapTuple tuple; + HeapTuple tuple; + char *result; - tuple = SearchSysCacheTuple(SHADOWSYSID, ObjectIdGetDatum(userid), 0, 0, 0); + tuple = SearchSysCache(SHADOWSYSID, + ObjectIdGetDatum(userid), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "invalid user id %u", (unsigned) userid); - return pstrdup( NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename) ); + result = pstrdup( NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename) ); + + ReleaseSysCache(tuple); + return result; } diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 3a9e5a1797b..bee4f7e9219 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.71 2000/11/14 18:37:44 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.72 2000/11/16 22:30:39 tgl Exp $ * * *------------------------------------------------------------------------- @@ -320,10 +320,7 @@ InitPostgres(const char *dbname, const char *username) /* * Initialize all the system catalog caches. - */ - zerocaches(); - - /* + * * Does not touch files since all routines are builtins (?) - thomas * 1997-11-01 */ diff --git a/src/backend/utils/misc/superuser.c b/src/backend/utils/misc/superuser.c index 1852b35e465..5139247291d 100644 --- a/src/backend/utils/misc/superuser.c +++ b/src/backend/utils/misc/superuser.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.15 2000/09/06 14:15:22 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.16 2000/11/16 22:30:40 tgl Exp $ * * DESCRIPTION * See superuser(). @@ -29,10 +29,16 @@ superuser(void) privileges. --------------------------------------------------------------------------*/ HeapTuple utup; + bool result; - utup = SearchSysCacheTuple(SHADOWSYSID, - ObjectIdGetDatum(GetUserId()), - 0, 0, 0); - Assert(utup != NULL); - return ((Form_pg_shadow) GETSTRUCT(utup))->usesuper; + utup = SearchSysCache(SHADOWSYSID, + ObjectIdGetDatum(GetUserId()), + 0, 0, 0); + if (HeapTupleIsValid(utup)) + { + result = ((Form_pg_shadow) GETSTRUCT(utup))->usesuper; + ReleaseSysCache(utup); + return result; + } + return false; } diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c index 1a0781dd921..a3c0784786d 100644 --- a/src/backend/utils/sort/tuplesort.c +++ b/src/backend/utils/sort/tuplesort.c @@ -78,7 +78,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplesort.c,v 1.10 2000/05/30 04:24:54 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplesort.c,v 1.11 2000/11/16 22:30:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -88,7 +88,6 @@ #include "access/heapam.h" #include "access/nbtree.h" #include "miscadmin.h" -#include "parser/parse_type.h" #include "utils/logtape.h" #include "utils/lsyscache.h" #include "utils/tuplesort.h" @@ -506,7 +505,8 @@ tuplesort_begin_datum(Oid datumType, bool randomAccess) { Tuplesortstate *state = tuplesort_begin_common(randomAccess); - Type typeInfo; + int16 typlen; + bool typbyval; state->comparetup = comparetup_datum; state->copytup = copytup_datum; @@ -519,9 +519,9 @@ tuplesort_begin_datum(Oid datumType, /* lookup the function that implements the sort operator */ fmgr_info(get_opcode(sortOperator), &state->sortOpFn); /* lookup necessary attributes of the datum type */ - typeInfo = typeidType(datumType); - state->datumTypeLen = typeLen(typeInfo); - state->datumTypeByVal = typeByVal(typeInfo); + get_typlenbyval(datumType, &typlen, &typbyval); + state->datumTypeLen = typlen; + state->datumTypeByVal = typbyval; return state; } diff --git a/src/include/executor/hashjoin.h b/src/include/executor/hashjoin.h index 25a8174f294..28581ad425a 100644 --- a/src/include/executor/hashjoin.h +++ b/src/include/executor/hashjoin.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: hashjoin.h,v 1.19 2000/08/22 04:06:21 tgl Exp $ + * $Id: hashjoin.h,v 1.20 2000/11/16 22:30:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -73,8 +73,8 @@ typedef struct HashTableData * and outer sides of the hash are the same type, or at least * binary-compatible types. */ + int16 typLen; bool typByVal; - int typLen; /* * During 1st scan of inner relation, we get tuples from executor. If diff --git a/src/include/lib/dllist.h b/src/include/lib/dllist.h index 9e357a7fd76..9306d4e6b67 100644 --- a/src/include/lib/dllist.h +++ b/src/include/lib/dllist.h @@ -2,12 +2,11 @@ * * dllist.h * simple doubly linked list primitives - * the elements of the list are void* so the lists can contain - * anything + * the elements of the list are void* so the lists can contain anything * Dlelem can only be in one list at a time * * - * Here's a small example of how to use Dllist's : + * Here's a small example of how to use Dllists: * * Dllist *lst; * Dlelem *elt; @@ -24,10 +23,18 @@ * DLFreeElem(elt); -- free the element since we don't * use it anymore * + * + * It is also possible to use Dllist objects that are embedded in larger + * structures instead of being separately malloc'd. To do this, use + * DLInitElem() to initialize a Dllist field within a larger object. + * Don't forget to DLRemove() each field from its list (if any) before + * freeing the larger object! + * + * * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: dllist.h,v 1.13 2000/06/08 22:37:46 momjian Exp $ + * $Id: dllist.h,v 1.14 2000/11/16 22:30:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -35,7 +42,6 @@ #ifndef DLLIST_H #define DLLIST_H - struct Dllist; struct Dlelem; @@ -53,21 +59,27 @@ typedef struct Dllist Dlelem *dll_tail; } Dllist; -extern Dllist *DLNewList(void); /* initialize a new list */ -extern void DLFreeList(Dllist *); /* free up a list and all the +extern Dllist *DLNewList(void); /* allocate and initialize a list header */ +extern void DLInitList(Dllist *list); /* init a header alloced by caller */ +extern void DLFreeList(Dllist *list); /* free up a list and all the * nodes in it */ extern Dlelem *DLNewElem(void *val); -extern void DLFreeElem(Dlelem *); -extern Dlelem *DLGetHead(Dllist *); -extern Dlelem *DLGetTail(Dllist *); -extern Dlelem *DLRemTail(Dllist *l); -extern Dlelem *DLGetSucc(Dlelem *); /* get successor */ -extern void DLRemove(Dlelem *); /* removes node from list */ +extern void DLInitElem(Dlelem *e, void *val); +extern void DLFreeElem(Dlelem *e); +extern void DLRemove(Dlelem *e); /* removes node from list */ extern void DLAddHead(Dllist *list, Dlelem *node); extern void DLAddTail(Dllist *list, Dlelem *node); extern Dlelem *DLRemHead(Dllist *list); /* remove and return the head */ -extern void DLMoveToFront(Dlelem *); /* move node to front of its list */ +extern Dlelem *DLRemTail(Dllist *list); +extern void DLMoveToFront(Dlelem *e); /* move node to front of its list */ + +/* These are macros for speed */ +#define DLGetHead(list) ((list)->dll_head) +#define DLGetTail(list) ((list)->dll_tail) +#define DLGetSucc(elem) ((elem)->dle_next) +#define DLGetPred(elem) ((elem)->dle_prev) +#define DLGetListHdr(elem) ((elem)->dle_list) -#define DLE_VAL(x) (x->dle_val) +#define DLE_VAL(elem) ((elem)->dle_val) #endif /* DLLIST_H */ diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h index 1ec37fc7b6f..08b0007fcaf 100644 --- a/src/include/nodes/makefuncs.h +++ b/src/include/nodes/makefuncs.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: makefuncs.h,v 1.25 2000/08/08 15:42:59 tgl Exp $ + * $Id: makefuncs.h,v 1.26 2000/11/16 22:30:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -42,7 +42,8 @@ extern Const *makeConst(Oid consttype, bool constisset, bool constiscast); -extern Attr * - makeAttr(char *relname, char *attname); +extern Const *makeNullConst(Oid consttype); + +extern Attr *makeAttr(char *relname, char *attname); #endif /* MAKEFUNC_H */ diff --git a/src/include/parser/parse_oper.h b/src/include/parser/parse_oper.h index 4162cd6d234..4e3c784c0dc 100644 --- a/src/include/parser/parse_oper.h +++ b/src/include/parser/parse_oper.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parse_oper.h,v 1.11 2000/01/26 05:58:27 momjian Exp $ + * $Id: parse_oper.h,v 1.12 2000/11/16 22:30:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -18,10 +18,13 @@ typedef HeapTuple Operator; -extern Oid any_ordering_op(Oid restype); -extern Oid oprid(Operator op); -extern Operator oper(char *op, Oid arg1, Oid arg2, bool noWarnings); +extern Operator oper(char *op, Oid arg1, Oid arg2, bool noError); extern Operator right_oper(char *op, Oid arg); extern Operator left_oper(char *op, Oid arg); +extern Oid oper_oid(char *op, Oid arg1, Oid arg2, bool noError); +extern Oid oprid(Operator op); + +extern Oid any_ordering_op(Oid restype); + #endif /* PARSE_OPER_H */ diff --git a/src/include/parser/parse_type.h b/src/include/parser/parse_type.h index e2cfd7f4a2d..0d8ba2f1bce 100644 --- a/src/include/parser/parse_type.h +++ b/src/include/parser/parse_type.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parse_type.h,v 1.14 2000/06/08 22:37:53 momjian Exp $ + * $Id: parse_type.h,v 1.15 2000/11/16 22:30:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,15 +21,18 @@ typedef HeapTuple Type; extern bool typeidIsValid(Oid id); extern Type typeidType(Oid id); extern Type typenameType(char *s); -extern char *typeidTypeName(Oid id); + extern Oid typeTypeId(Type tp); extern int16 typeLen(Type t); extern bool typeByVal(Type t); extern char *typeTypeName(Type t); extern char typeTypeFlag(Type t); +extern Oid typeTypeRelid(Type typ); extern Datum stringTypeDatum(Type tp, char *string, int32 atttypmod); + +extern char *typeidTypeName(Oid id); extern Oid typeidTypeRelid(Oid type_id); -extern Oid typeTypeRelid(Type typ); +extern Oid typenameTypeId(char *s); #define ISCOMPLEX(typeid) (typeidTypeRelid(typeid) != InvalidOid) diff --git a/src/include/rewrite/rewriteSupport.h b/src/include/rewrite/rewriteSupport.h index 39605df47ad..20cf82cbd91 100644 --- a/src/include/rewrite/rewriteSupport.h +++ b/src/include/rewrite/rewriteSupport.h @@ -7,14 +7,14 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: rewriteSupport.h,v 1.13 2000/09/29 18:21:24 tgl Exp $ + * $Id: rewriteSupport.h,v 1.14 2000/11/16 22:30:46 tgl Exp $ * *------------------------------------------------------------------------- */ #ifndef REWRITESUPPORT_H #define REWRITESUPPORT_H -extern int IsDefinedRewriteRule(char *ruleName); +extern bool IsDefinedRewriteRule(char *ruleName); extern void SetRelationRuleStatus(Oid relationId, bool relHasRules, bool relIsBecomingView); diff --git a/src/include/utils/catcache.h b/src/include/utils/catcache.h index e55b6492d8c..ed78284a478 100644 --- a/src/include/utils/catcache.h +++ b/src/include/utils/catcache.h @@ -13,7 +13,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: catcache.h,v 1.27 2000/11/10 00:33:12 tgl Exp $ + * $Id: catcache.h,v 1.28 2000/11/16 22:30:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -32,18 +32,29 @@ typedef struct catctup { - HeapTuple ct_tup; /* A pointer to a tuple */ + int ct_magic; /* for Assert checks */ +#define CT_MAGIC 0x57261502 + /* - * Each tuple in the cache has two catctup items, one in the LRU list - * and one in the hashbucket list for its hash value. ct_node in each - * one points to the other one. + * Each tuple in a cache is a member of two lists: one lists all the + * elements in that cache in LRU order, and the other lists just the + * elements in one hashbucket, also in LRU order. + * + * A tuple marked "dead" must not be returned by subsequent searches. + * However, it won't be physically deleted from the cache until its + * refcount goes to zero. */ - Dlelem *ct_node; /* the other catctup for this tuple */ + Dlelem lrulist_elem; /* list member of global LRU list */ + Dlelem cache_elem; /* list member of per-bucket list */ + int refcount; /* number of active references */ + bool dead; /* dead but not yet removed? */ + HeapTupleData tuple; /* tuple management header */ } CatCTup; + /* voodoo constants */ #define NCCBUCK 500 /* CatCache buckets */ -#define MAXTUP 300 /* Maximum # of tuples stored per cache */ +#define MAXTUP 500 /* Maximum # of tuples stored per cache */ typedef struct catcache @@ -60,8 +71,8 @@ typedef struct catcache short cc_key[4]; /* AttrNumber of each key */ PGFunction cc_hashfunc[4]; /* hash function to use for each key */ ScanKeyData cc_skey[4]; /* precomputed key info for indexscans */ - Dllist *cc_lrulist; /* LRU list, most recent first */ - Dllist *cc_cache[NCCBUCK + 1]; /* hash buckets */ + Dllist cc_lrulist; /* overall LRU list, most recent first */ + Dllist cc_cache[NCCBUCK]; /* hash buckets */ } CatCache; #define InvalidCatalogCacheId (-1) @@ -70,12 +81,15 @@ typedef struct catcache extern MemoryContext CacheMemoryContext; extern void CreateCacheMemoryContext(void); +extern void AtEOXact_CatCache(bool isCommit); -extern CatCache *InitSysCache(int id, char *relname, char *indname, +extern CatCache *InitCatCache(int id, char *relname, char *indname, int nkeys, int *key); -extern HeapTuple SearchSysCache(CatCache *cache, + +extern HeapTuple SearchCatCache(CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4); +extern void ReleaseCatCache(HeapTuple tuple); extern void ResetSystemCache(void); extern void SystemCacheRelationFlushed(Oid relId); diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index 516949d1de9..f8547baa884 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: lsyscache.h,v 1.26 2000/10/05 19:48:34 momjian Exp $ + * $Id: lsyscache.h,v 1.27 2000/11/16 22:30:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -29,7 +29,6 @@ extern bool op_mergejoinable(Oid opno, Oid ltype, Oid rtype, Oid *leftOp, Oid *rightOp); extern Oid op_hashjoinable(Oid opno, Oid ltype, Oid rtype); extern bool op_iscachable(Oid opno); -extern HeapTuple get_operator_tuple(Oid opno); extern Oid get_commutator(Oid opno); extern Oid get_negator(Oid opno); extern RegProcedure get_oprrest(Oid opno); @@ -39,6 +38,7 @@ extern bool func_iscachable(Oid funcid); extern char *get_rel_name(Oid relid); extern int16 get_typlen(Oid typid); extern bool get_typbyval(Oid typid); +extern void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval); extern Datum get_typdefault(Oid typid); #endif /* LSYSCACHE_H */ diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h index 5d17e8db44c..73abd53e134 100644 --- a/src/include/utils/syscache.h +++ b/src/include/utils/syscache.h @@ -9,7 +9,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: syscache.h,v 1.26 2000/06/17 04:56:29 tgl Exp $ + * $Id: syscache.h,v 1.27 2000/11/16 22:30:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -57,12 +57,22 @@ #define TYPENAME 26 #define TYPEOID 27 -extern void zerocaches(void); extern void InitCatalogCache(void); -extern HeapTuple SearchSysCacheTuple(int cacheId, + +extern HeapTuple SearchSysCache(int cacheId, + Datum key1, Datum key2, Datum key3, Datum key4); +extern void ReleaseSysCache(HeapTuple tuple); + +/* convenience routines */ +extern HeapTuple SearchSysCacheCopy(int cacheId, Datum key1, Datum key2, Datum key3, Datum key4); -extern HeapTuple SearchSysCacheTupleCopy(int cacheId, - Datum key1, Datum key2, Datum key3, Datum key4); +extern Oid GetSysCacheOid(int cacheId, + Datum key1, Datum key2, Datum key3, Datum key4); + +/* macro for just probing for existence of a tuple via the syscache */ +#define SearchSysCacheExists(c,k1,k2,k3,k4) \ + OidIsValid(GetSysCacheOid(c,k1,k2,k3,k4)) + extern Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull); diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index c1516ea6928..81a4cd75d4b 100644 --- a/src/pl/plperl/plperl.c +++ b/src/pl/plperl/plperl.c @@ -33,7 +33,7 @@ * ENHANCEMENTS, OR MODIFICATIONS. * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.14 2000/10/24 17:01:05 tgl Exp $ + * $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.15 2000/11/16 22:30:49 tgl Exp $ * **********************************************************************/ @@ -521,9 +521,9 @@ plperl_func_handler(PG_FUNCTION_ARGS) /************************************************************ * Lookup the pg_proc tuple by Oid ************************************************************/ - procTup = SearchSysCacheTuple(PROCOID, - ObjectIdGetDatum(fcinfo->flinfo->fn_oid), - 0, 0, 0); + procTup = SearchSysCache(PROCOID, + ObjectIdGetDatum(fcinfo->flinfo->fn_oid), + 0, 0, 0); if (!HeapTupleIsValid(procTup)) { free(prodesc->proname); @@ -537,9 +537,9 @@ plperl_func_handler(PG_FUNCTION_ARGS) * Get the required information for input conversion of the * return value. ************************************************************/ - typeTup = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(procStruct->prorettype), - 0, 0, 0); + typeTup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(procStruct->prorettype), + 0, 0, 0); if (!HeapTupleIsValid(typeTup)) { free(prodesc->proname); @@ -560,6 +560,8 @@ plperl_func_handler(PG_FUNCTION_ARGS) prodesc->result_in_elem = (Oid) (typeStruct->typelem); prodesc->result_in_len = typeStruct->typlen; + ReleaseSysCache(typeTup); + /************************************************************ * Get the required information for output conversion * of all procedure arguments @@ -567,9 +569,9 @@ plperl_func_handler(PG_FUNCTION_ARGS) prodesc->nargs = procStruct->pronargs; for (i = 0; i < prodesc->nargs; i++) { - typeTup = SearchSysCacheTuple(TYPEOID, + typeTup = SearchSysCache(TYPEOID, ObjectIdGetDatum(procStruct->proargtypes[i]), - 0, 0, 0); + 0, 0, 0); if (!HeapTupleIsValid(typeTup)) { free(prodesc->proname); @@ -587,7 +589,7 @@ plperl_func_handler(PG_FUNCTION_ARGS) fmgr_info(typeStruct->typoutput, &(prodesc->arg_out_func[i])); prodesc->arg_out_elem[i] = (Oid) (typeStruct->typelem); prodesc->arg_out_len[i] = typeStruct->typlen; - + ReleaseSysCache(typeTup); } /************************************************************ @@ -617,6 +619,8 @@ plperl_func_handler(PG_FUNCTION_ARGS) ************************************************************/ hv_store(plperl_proc_hash, internal_proname, proname_len, newSViv((IV) prodesc), 0); + + ReleaseSysCache(procTup); } else { @@ -744,9 +748,9 @@ plperl_trigger_handler(PG_FUNCTION_ARGS) /************************************************************ * Lookup the pg_proc tuple by Oid ************************************************************/ - procTup = SearchSysCacheTuple(PROCOID, - ObjectIdGetDatum(fcinfo->flinfo->fn_oid), - 0, 0, 0); + procTup = SearchSysCache(PROCOID, + ObjectIdGetDatum(fcinfo->flinfo->fn_oid), + 0, 0, 0); if (!HeapTupleIsValid(procTup)) { free(prodesc->proname); @@ -819,6 +823,8 @@ plperl_trigger_handler(PG_FUNCTION_ARGS) hashent = Tcl_CreateHashEntry(plperl_proc_hash, prodesc->proname, &hashnew); Tcl_SetHashValue(hashent, (ClientData) prodesc); + + ReleaseSysCache(procTup); } else { @@ -1068,9 +1074,9 @@ plperl_trigger_handler(PG_FUNCTION_ARGS) * Lookup the attribute type in the syscache * for the input function ************************************************************/ - typeTup = SearchSysCacheTuple(TYPEOID, + typeTup = SearchSysCache(TYPEOID, ObjectIdGetDatum(tupdesc->attrs[attnum - 1]->atttypid), - 0, 0, 0); + 0, 0, 0); if (!HeapTupleIsValid(typeTup)) { elog(ERROR, "plperl: Cache lookup for attribute '%s' type %u failed", @@ -1079,6 +1085,7 @@ plperl_trigger_handler(PG_FUNCTION_ARGS) } typinput = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typinput); typelem = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typelem); + ReleaseSysCache(typeTup); /************************************************************ * Set the attribute to NOT NULL and convert the contents @@ -1538,9 +1545,9 @@ plperl_SPI_prepare(ClientData cdata, Tcl_Interp *interp, ************************************************************/ for (i = 0; i < nargs; i++) { - typeTup = SearchSysCacheTuple(TYPNAME, - PointerGetDatum(args[i]), - 0, 0, 0); + typeTup = SearchSysCache(TYPNAME, + PointerGetDatum(args[i]), + 0, 0, 0); if (!HeapTupleIsValid(typeTup)) elog(ERROR, "plperl: Cache lookup of type %s failed", args[i]); qdesc->argtypes[i] = typeTup->t_data->t_oid; @@ -1549,6 +1556,7 @@ plperl_SPI_prepare(ClientData cdata, Tcl_Interp *interp, qdesc->argtypelems[i] = ((Form_pg_type) GETSTRUCT(typeTup))->typelem; qdesc->argvalues[i] = (Datum) NULL; qdesc->arglen[i] = (int) (((Form_pg_type) GETSTRUCT(typeTup))->typlen); + ReleaseSysCache(typeTup); } /************************************************************ @@ -2084,9 +2092,9 @@ plperl_set_tuple_values(Tcl_Interp *interp, char *arrayname, * Lookup the attribute type in the syscache * for the output function ************************************************************/ - typeTup = SearchSysCacheTuple(TYPEOID, + typeTup = SearchSysCache(TYPEOID, ObjectIdGetDatum(tupdesc->attrs[i]->atttypid), - 0, 0, 0); + 0, 0, 0); if (!HeapTupleIsValid(typeTup)) { elog(ERROR, "plperl: Cache lookup for attribute '%s' type %u failed", @@ -2095,6 +2103,7 @@ plperl_set_tuple_values(Tcl_Interp *interp, char *arrayname, typoutput = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typoutput); typelem = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typelem); + ReleaseSysCache(typeTup); /************************************************************ * If there is a value, set the variable @@ -2156,9 +2165,9 @@ plperl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc) * Lookup the attribute type in the syscache * for the output function ************************************************************/ - typeTup = SearchSysCacheTuple(TYPEOID, + typeTup = SearchSysCache(TYPEOID, ObjectIdGetDatum(tupdesc->attrs[i]->atttypid), - 0, 0, 0); + 0, 0, 0); if (!HeapTupleIsValid(typeTup)) { elog(ERROR, "plperl: Cache lookup for attribute '%s' type %u failed", @@ -2167,6 +2176,7 @@ plperl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc) typoutput = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typoutput); typelem = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typelem); + ReleaseSysCache(typeTup); /************************************************************ * If there is a value, append the attribute name and the diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c index bed95890968..c0fe5968970 100644 --- a/src/pl/plpgsql/src/pl_comp.c +++ b/src/pl/plpgsql/src/pl_comp.c @@ -3,7 +3,7 @@ * procedural language * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.23 2000/08/31 13:26:16 wieck Exp $ + * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.24 2000/11/16 22:30:50 tgl Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -53,7 +53,6 @@ #include "access/heapam.h" #include "utils/syscache.h" -#include "utils/catcache.h" #include "catalog/catname.h" #include "catalog/pg_proc.h" #include "catalog/pg_type.h" @@ -131,9 +130,9 @@ plpgsql_compile(Oid fn_oid, int functype) * Lookup the pg_proc tuple by Oid * ---------- */ - procTup = SearchSysCacheTuple(PROCOID, - ObjectIdGetDatum(fn_oid), - 0, 0, 0); + procTup = SearchSysCache(PROCOID, + ObjectIdGetDatum(fn_oid), + 0, 0, 0); if (!HeapTupleIsValid(procTup)) elog(ERROR, "plpgsql: cache lookup for proc %u failed", fn_oid); @@ -176,9 +175,9 @@ plpgsql_compile(Oid fn_oid, int functype) * Lookup the functions return type * ---------- */ - typeTup = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(procStruct->prorettype), 0, 0, 0); - + typeTup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(procStruct->prorettype), + 0, 0, 0); if (!HeapTupleIsValid(typeTup)) { plpgsql_comperrinfo(); @@ -195,6 +194,7 @@ plpgsql_compile(Oid fn_oid, int functype) function->fn_rettypelem = typeStruct->typelem; fmgr_info(typeStruct->typinput, &(function->fn_retinput)); } + ReleaseSysCache(typeTup); /* ---------- * Create the variables for the procedures parameters @@ -208,9 +208,9 @@ plpgsql_compile(Oid fn_oid, int functype) * Get the parameters type * ---------- */ - typeTup = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(procStruct->proargtypes[i]), 0, 0, 0); - + typeTup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(procStruct->proargtypes[i]), + 0, 0, 0); if (!HeapTupleIsValid(typeTup)) { plpgsql_comperrinfo(); @@ -276,6 +276,7 @@ plpgsql_compile(Oid fn_oid, int functype) arg_varnos[i] = var->varno; } + ReleaseSysCache(typeTup); } break; @@ -512,6 +513,7 @@ plpgsql_compile(Oid fn_oid, int functype) function->datums[i] = plpgsql_Datums[i]; function->action = plpgsql_yylval.program; + ReleaseSysCache(procTup); /* ---------- * Finally return the compiled function @@ -608,8 +610,9 @@ plpgsql_parse_word(char *word) * ---------- */ typeXlated = xlateSqlType(cp); - typeTup = SearchSysCacheTuple(TYPENAME, - PointerGetDatum(typeXlated), 0, 0, 0); + typeTup = SearchSysCache(TYPENAME, + PointerGetDatum(typeXlated), + 0, 0, 0); if (HeapTupleIsValid(typeTup)) { PLpgSQL_type *typ; @@ -618,6 +621,7 @@ plpgsql_parse_word(char *word) if (typeStruct->typrelid != InvalidOid) { + ReleaseSysCache(typeTup); pfree(cp); return T_WORD; } @@ -634,6 +638,7 @@ plpgsql_parse_word(char *word) plpgsql_yylval.dtype = typ; + ReleaseSysCache(typeTup); pfree(cp); return T_DTYPE; } @@ -933,8 +938,9 @@ plpgsql_parse_wordtype(char *word) * ---------- */ typeXlated = xlateSqlType(cp); - typeTup = SearchSysCacheTuple(TYPENAME, - PointerGetDatum(typeXlated), 0, 0, 0); + typeTup = SearchSysCache(TYPENAME, + PointerGetDatum(typeXlated), + 0, 0, 0); if (HeapTupleIsValid(typeTup)) { PLpgSQL_type *typ; @@ -943,6 +949,7 @@ plpgsql_parse_wordtype(char *word) if (typeStruct->typrelid != InvalidOid) { + ReleaseSysCache(typeTup); pfree(cp); return T_ERROR; } @@ -959,6 +966,7 @@ plpgsql_parse_wordtype(char *word) plpgsql_yylval.dtype = typ; + ReleaseSysCache(typeTup); pfree(cp); return T_DTYPE; } @@ -1045,8 +1053,9 @@ plpgsql_parse_dblwordtype(char *string) * First word could also be a table name * ---------- */ - classtup = SearchSysCacheTuple(RELNAME, - PointerGetDatum(word1), 0, 0, 0); + classtup = SearchSysCache(RELNAME, + PointerGetDatum(word1), + 0, 0, 0); if (!HeapTupleIsValid(classtup)) { pfree(word1); @@ -1060,6 +1069,7 @@ plpgsql_parse_dblwordtype(char *string) classStruct = (Form_pg_class) GETSTRUCT(classtup); if (classStruct->relkind != 'r' && classStruct->relkind != 's') { + ReleaseSysCache(classtup); pfree(word1); return T_ERROR; } @@ -1068,31 +1078,33 @@ plpgsql_parse_dblwordtype(char *string) * Fetch the named table field and it's type * ---------- */ - attrtup = SearchSysCacheTuple(ATTNAME, - ObjectIdGetDatum(classtup->t_data->t_oid), - PointerGetDatum(word2), 0, 0); + attrtup = SearchSysCache(ATTNAME, + ObjectIdGetDatum(classtup->t_data->t_oid), + PointerGetDatum(word2), + 0, 0); if (!HeapTupleIsValid(attrtup)) { + ReleaseSysCache(classtup); pfree(word1); return T_ERROR; } attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup); - typetup = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(attrStruct->atttypid), 0, 0, 0); + typetup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(attrStruct->atttypid), + 0, 0, 0); if (!HeapTupleIsValid(typetup)) { plpgsql_comperrinfo(); elog(ERROR, "cache lookup for type %u of %s.%s failed", attrStruct->atttypid, word1, word2); } + typeStruct = (Form_pg_type) GETSTRUCT(typetup); /* ---------- * Found that - build a compiler type struct and return it * ---------- */ - typeStruct = (Form_pg_type) GETSTRUCT(typetup); - typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type)); typ->typname = DatumGetCString(DirectFunctionCall1(nameout, @@ -1105,6 +1117,9 @@ plpgsql_parse_dblwordtype(char *string) plpgsql_yylval.dtype = typ; + ReleaseSysCache(classtup); + ReleaseSysCache(attrtup); + ReleaseSysCache(typetup); pfree(word1); return T_DTYPE; } @@ -1138,8 +1153,9 @@ plpgsql_parse_wordrowtype(char *string) cp = strchr(word1, '%'); *cp = '\0'; - classtup = SearchSysCacheTuple(RELNAME, - PointerGetDatum(word1), 0, 0, 0); + classtup = SearchSysCache(RELNAME, + PointerGetDatum(word1), + 0, 0, 0); if (!HeapTupleIsValid(classtup)) { plpgsql_comperrinfo(); @@ -1156,8 +1172,9 @@ plpgsql_parse_wordrowtype(char *string) * Fetch the tables pg_type tuple too * ---------- */ - typetup = SearchSysCacheTuple(TYPENAME, - PointerGetDatum(word1), 0, 0, 0); + typetup = SearchSysCache(TYPENAME, + PointerGetDatum(word1), + 0, 0, 0); if (!HeapTupleIsValid(typetup)) { plpgsql_comperrinfo(); @@ -1178,15 +1195,18 @@ plpgsql_parse_wordrowtype(char *string) row->fieldnames = malloc(sizeof(char *) * row->nfields); row->varnos = malloc(sizeof(int) * row->nfields); + ReleaseSysCache(typetup); + for (i = 0; i < row->nfields; i++) { /* ---------- * Get the attribute and it's type * ---------- */ - attrtup = SearchSysCacheTuple(ATTNUM, - ObjectIdGetDatum(classtup->t_data->t_oid), - (Datum) (i + 1), 0, 0); + attrtup = SearchSysCache(ATTNUM, + ObjectIdGetDatum(classtup->t_data->t_oid), + Int16GetDatum(i + 1), + 0, 0); if (!HeapTupleIsValid(attrtup)) { plpgsql_comperrinfo(); @@ -1198,8 +1218,9 @@ plpgsql_parse_wordrowtype(char *string) cp = DatumGetCString(DirectFunctionCall1(nameout, NameGetDatum(&(attrStruct->attname)))); - typetup = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(attrStruct->atttypid), 0, 0, 0); + typetup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(attrStruct->atttypid), + 0, 0, 0); if (!HeapTupleIsValid(typetup)) { plpgsql_comperrinfo(); @@ -1238,6 +1259,9 @@ plpgsql_parse_wordrowtype(char *string) var->isnull = true; var->shouldfree = false; + ReleaseSysCache(typetup); + ReleaseSysCache(attrtup); + plpgsql_adddatum((PLpgSQL_datum *) var); /* ---------- @@ -1248,6 +1272,8 @@ plpgsql_parse_wordrowtype(char *string) row->varnos[i] = var->varno; } + ReleaseSysCache(classtup); + /* ---------- * Return the complete row definition * ---------- diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 9c094a0739a..565e304f649 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -3,7 +3,7 @@ * procedural language * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.31 2000/09/12 19:41:40 tgl Exp $ + * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.32 2000/11/16 22:30:50 tgl Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -1641,10 +1641,12 @@ exec_stmt_raise(PLpgSQL_execstate * estate, PLpgSQL_stmt_raise * stmt) extval = "<NULL>"; else { - typetup = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(var->datatype->typoid), 0, 0, 0); + typetup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(var->datatype->typoid), + 0, 0, 0); if (!HeapTupleIsValid(typetup)) - elog(ERROR, "cache lookup for type %u failed (1)", var->datatype->typoid); + elog(ERROR, "cache lookup for type %u failed (1)", + var->datatype->typoid); typeStruct = (Form_pg_type) GETSTRUCT(typetup); fmgr_info(typeStruct->typoutput, &finfo_output); @@ -1652,6 +1654,7 @@ exec_stmt_raise(PLpgSQL_execstate * estate, PLpgSQL_stmt_raise * stmt) var->value, ObjectIdGetDatum(typeStruct->typelem), Int32GetDatum(var->datatype->atttypmod))); + ReleaseSysCache(typetup); } plpgsql_dstring_append(&ds, extval); break; @@ -1961,21 +1964,24 @@ exec_stmt_dynexecute(PLpgSQL_execstate * estate, * Get the C-String representation. * ---------- */ - typetup = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(restype), 0, 0, 0); + typetup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(restype), + 0, 0, 0); if (!HeapTupleIsValid(typetup)) elog(ERROR, "cache lookup for type %u failed (1)", restype); typeStruct = (Form_pg_type) GETSTRUCT(typetup); fmgr_info(typeStruct->typoutput, &finfo_output); querystr = DatumGetCString(FunctionCall3(&finfo_output, - query, - ObjectIdGetDatum(typeStruct->typelem), - Int32GetDatum(-1))); + query, + ObjectIdGetDatum(typeStruct->typelem), + Int32GetDatum(-1))); if(!typeStruct->typbyval) pfree((void *)query); + ReleaseSysCache(typetup); + /* ---------- * Call SPI_exec() without preparing a saved plan. * The returncode can be any OK except for OK_SELECT. @@ -2064,8 +2070,9 @@ exec_stmt_dynfors(PLpgSQL_execstate * estate, PLpgSQL_stmt_dynfors * stmt) * Get the C-String representation. * ---------- */ - typetup = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(restype), 0, 0, 0); + typetup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(restype), + 0, 0, 0); if (!HeapTupleIsValid(typetup)) elog(ERROR, "cache lookup for type %u failed (1)", restype); typeStruct = (Form_pg_type) GETSTRUCT(typetup); @@ -2079,6 +2086,8 @@ exec_stmt_dynfors(PLpgSQL_execstate * estate, PLpgSQL_stmt_dynfors * stmt) if(!typeStruct->typbyval) pfree((void *)query); + ReleaseSysCache(typetup); + /* ---------- * Run the query * ---------- @@ -2283,8 +2292,9 @@ exec_assign_value(PLpgSQL_execstate * estate, */ atttype = SPI_gettypeid(rec->tupdesc, i + 1); atttypmod = rec->tupdesc->attrs[i]->atttypmod; - typetup = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(atttype), 0, 0, 0); + typetup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(atttype), + 0, 0, 0); if (!HeapTupleIsValid(typetup)) elog(ERROR, "cache lookup for type %u failed", atttype); typeStruct = (Form_pg_type) GETSTRUCT(typetup); @@ -2299,6 +2309,7 @@ exec_assign_value(PLpgSQL_execstate * estate, nulls[i] = 'n'; else nulls[i] = ' '; + ReleaseSysCache(typetup); } /* ---------- @@ -2603,9 +2614,13 @@ exec_eval_simple_expr(PLpgSQL_execstate * estate, * so that we can free the expression context. */ if (! *isNull) - retval = datumCopy(retval, - get_typbyval(*rettype), - get_typlen(*rettype)); + { + int16 typeLength; + bool byValue; + + get_typlenbyval(*rettype, &typeLength, &byValue); + retval = datumCopy(retval, byValue, typeLength); + } FreeExprContext(econtext); @@ -2726,8 +2741,9 @@ exec_cast_value(Datum value, Oid valtype, FmgrInfo finfo_output; char *extval; - typetup = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(valtype), 0, 0, 0); + typetup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(valtype), + 0, 0, 0); if (!HeapTupleIsValid(typetup)) elog(ERROR, "cache lookup for type %u failed", valtype); typeStruct = (Form_pg_type) GETSTRUCT(typetup); @@ -2742,6 +2758,7 @@ exec_cast_value(Datum value, Oid valtype, ObjectIdGetDatum(reqtypelem), Int32GetDatum(reqtypmod)); pfree(extval); + ReleaseSysCache(typetup); } } diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c index 0c2ec992b7b..8658cac3065 100644 --- a/src/pl/tcl/pltcl.c +++ b/src/pl/tcl/pltcl.c @@ -31,7 +31,7 @@ * ENHANCEMENTS, OR MODIFICATIONS. * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.28 2000/07/19 11:53:02 wieck Exp $ + * $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.29 2000/11/16 22:30:52 tgl Exp $ * **********************************************************************/ @@ -437,9 +437,9 @@ pltcl_func_handler(PG_FUNCTION_ARGS) /************************************************************ * Lookup the pg_proc tuple by Oid ************************************************************/ - procTup = SearchSysCacheTuple(PROCOID, - ObjectIdGetDatum(fcinfo->flinfo->fn_oid), - 0, 0, 0); + procTup = SearchSysCache(PROCOID, + ObjectIdGetDatum(fcinfo->flinfo->fn_oid), + 0, 0, 0); if (!HeapTupleIsValid(procTup)) { free(prodesc->proname); @@ -452,9 +452,9 @@ pltcl_func_handler(PG_FUNCTION_ARGS) /************************************************************ * Lookup the pg_language tuple by Oid ************************************************************/ - langTup = SearchSysCacheTuple(LANGOID, - ObjectIdGetDatum(procStruct->prolang), - 0, 0, 0); + langTup = SearchSysCache(LANGOID, + ObjectIdGetDatum(procStruct->prolang), + 0, 0, 0); if (!HeapTupleIsValid(langTup)) { free(prodesc->proname); @@ -469,14 +469,15 @@ pltcl_func_handler(PG_FUNCTION_ARGS) interp = pltcl_safe_interp; else interp = pltcl_norm_interp; + ReleaseSysCache(langTup); /************************************************************ * Get the required information for input conversion of the * return value. ************************************************************/ - typeTup = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(procStruct->prorettype), - 0, 0, 0); + typeTup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(procStruct->prorettype), + 0, 0, 0); if (!HeapTupleIsValid(typeTup)) { free(prodesc->proname); @@ -496,6 +497,8 @@ pltcl_func_handler(PG_FUNCTION_ARGS) fmgr_info(typeStruct->typinput, &(prodesc->result_in_func)); prodesc->result_in_elem = typeStruct->typelem; + ReleaseSysCache(typeTup); + /************************************************************ * Get the required information for output conversion * of all procedure arguments @@ -504,9 +507,9 @@ pltcl_func_handler(PG_FUNCTION_ARGS) proc_internal_args[0] = '\0'; for (i = 0; i < prodesc->nargs; i++) { - typeTup = SearchSysCacheTuple(TYPEOID, + typeTup = SearchSysCache(TYPEOID, ObjectIdGetDatum(procStruct->proargtypes[i]), - 0, 0, 0); + 0, 0, 0); if (!HeapTupleIsValid(typeTup)) { free(prodesc->proname); @@ -523,6 +526,7 @@ pltcl_func_handler(PG_FUNCTION_ARGS) strcat(proc_internal_args, " "); sprintf(buf, "__PLTcl_Tup_%d", i + 1); strcat(proc_internal_args, buf); + ReleaseSysCache(typeTup); continue; } else @@ -536,6 +540,8 @@ pltcl_func_handler(PG_FUNCTION_ARGS) strcat(proc_internal_args, " "); sprintf(buf, "%d", i + 1); strcat(proc_internal_args, buf); + + ReleaseSysCache(typeTup); } /************************************************************ @@ -591,6 +597,8 @@ pltcl_func_handler(PG_FUNCTION_ARGS) hashent = Tcl_CreateHashEntry(pltcl_proc_hash, prodesc->proname, &hashnew); Tcl_SetHashValue(hashent, (ClientData) prodesc); + + ReleaseSysCache(procTup); } else { @@ -800,9 +808,9 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS) /************************************************************ * Lookup the pg_proc tuple by Oid ************************************************************/ - procTup = SearchSysCacheTuple(PROCOID, - ObjectIdGetDatum(fcinfo->flinfo->fn_oid), - 0, 0, 0); + procTup = SearchSysCache(PROCOID, + ObjectIdGetDatum(fcinfo->flinfo->fn_oid), + 0, 0, 0); if (!HeapTupleIsValid(procTup)) { free(prodesc->proname); @@ -815,9 +823,9 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS) /************************************************************ * Lookup the pg_language tuple by Oid ************************************************************/ - langTup = SearchSysCacheTuple(LANGOID, - ObjectIdGetDatum(procStruct->prolang), - 0, 0, 0); + langTup = SearchSysCache(LANGOID, + ObjectIdGetDatum(procStruct->prolang), + 0, 0, 0); if (!HeapTupleIsValid(langTup)) { free(prodesc->proname); @@ -832,6 +840,7 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS) interp = pltcl_safe_interp; else interp = pltcl_norm_interp; + ReleaseSysCache(langTup); /************************************************************ * Create the tcl command to define the internal @@ -896,6 +905,8 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS) hashent = Tcl_CreateHashEntry(pltcl_proc_hash, prodesc->proname, &hashnew); Tcl_SetHashValue(hashent, (ClientData) prodesc); + + ReleaseSysCache(procTup); } else { @@ -1151,9 +1162,9 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS) * Lookup the attribute type in the syscache * for the input function ************************************************************/ - typeTup = SearchSysCacheTuple(TYPEOID, + typeTup = SearchSysCache(TYPEOID, ObjectIdGetDatum(tupdesc->attrs[attnum - 1]->atttypid), - 0, 0, 0); + 0, 0, 0); if (!HeapTupleIsValid(typeTup)) { elog(ERROR, "pltcl: Cache lookup for attribute '%s' type %u failed", @@ -1162,6 +1173,7 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS) } typinput = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typinput); typelem = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typelem); + ReleaseSysCache(typeTup); /************************************************************ * Set the attribute to NOT NULL and convert the contents @@ -1706,9 +1718,9 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp, ************************************************************/ for (i = 0; i < nargs; i++) { - typeTup = SearchSysCacheTuple(TYPENAME, - PointerGetDatum(args[i]), - 0, 0, 0); + typeTup = SearchSysCache(TYPENAME, + PointerGetDatum(args[i]), + 0, 0, 0); if (!HeapTupleIsValid(typeTup)) elog(ERROR, "pltcl: Cache lookup of type %s failed", args[i]); qdesc->argtypes[i] = typeTup->t_data->t_oid; @@ -1717,6 +1729,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp, qdesc->argtypelems[i] = ((Form_pg_type) GETSTRUCT(typeTup))->typelem; qdesc->argvalues[i] = (Datum) NULL; qdesc->arglen[i] = (int) (((Form_pg_type) GETSTRUCT(typeTup))->typlen); + ReleaseSysCache(typeTup); } /************************************************************ @@ -2263,9 +2276,9 @@ pltcl_set_tuple_values(Tcl_Interp *interp, char *arrayname, * Lookup the attribute type in the syscache * for the output function ************************************************************/ - typeTup = SearchSysCacheTuple(TYPEOID, + typeTup = SearchSysCache(TYPEOID, ObjectIdGetDatum(tupdesc->attrs[i]->atttypid), - 0, 0, 0); + 0, 0, 0); if (!HeapTupleIsValid(typeTup)) { elog(ERROR, "pltcl: Cache lookup for attribute '%s' type %u failed", @@ -2274,6 +2287,7 @@ pltcl_set_tuple_values(Tcl_Interp *interp, char *arrayname, typoutput = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typoutput); typelem = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typelem); + ReleaseSysCache(typeTup); /************************************************************ * If there is a value, set the variable @@ -2332,9 +2346,9 @@ pltcl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc, * Lookup the attribute type in the syscache * for the output function ************************************************************/ - typeTup = SearchSysCacheTuple(TYPEOID, + typeTup = SearchSysCache(TYPEOID, ObjectIdGetDatum(tupdesc->attrs[i]->atttypid), - 0, 0, 0); + 0, 0, 0); if (!HeapTupleIsValid(typeTup)) { elog(ERROR, "pltcl: Cache lookup for attribute '%s' type %u failed", @@ -2343,6 +2357,7 @@ pltcl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc, typoutput = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typoutput); typelem = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typelem); + ReleaseSysCache(typeTup); /************************************************************ * If there is a value, append the attribute name and the |