Change SearchSysCache coding conventions so that a reference count is
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 16 Nov 2000 22:30:52 +0000 (22:30 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 16 Nov 2000 22:30:52 +0000 (22:30 +0000)
maintained for each cache entry.  A cache entry will not be freed until
the matching ReleaseSysCache call has been executed.  This eliminates
worries about cache entries getting dropped while still in use.  See
my posting to pg-hackers of even date for more info.

95 files changed:
contrib/array/array_iterator.c
doc/FAQ_DEV
doc/src/FAQ/FAQ_DEV.html
src/backend/access/common/printtup.c
src/backend/access/common/tupdesc.c
src/backend/access/gist/gist.c
src/backend/access/index/istrat.c
src/backend/access/transam/xact.c
src/backend/catalog/aclchk.c
src/backend/catalog/catalog.c
src/backend/catalog/heap.c
src/backend/catalog/index.c
src/backend/catalog/indexing.c
src/backend/catalog/pg_aggregate.c
src/backend/catalog/pg_operator.c
src/backend/catalog/pg_proc.c
src/backend/catalog/pg_type.c
src/backend/commands/analyze.c
src/backend/commands/async.c
src/backend/commands/cluster.c
src/backend/commands/command.c
src/backend/commands/comment.c
src/backend/commands/copy.c
src/backend/commands/creatinh.c
src/backend/commands/dbcommands.c
src/backend/commands/define.c
src/backend/commands/indexcmds.c
src/backend/commands/proclang.c
src/backend/commands/remove.c
src/backend/commands/rename.c
src/backend/commands/trigger.c
src/backend/commands/user.c
src/backend/commands/vacuum.c
src/backend/executor/execUtils.c
src/backend/executor/functions.c
src/backend/executor/nodeAgg.c
src/backend/executor/nodeGroup.c
src/backend/executor/nodeHash.c
src/backend/executor/nodeMergejoin.c
src/backend/executor/spi.c
src/backend/lib/dllist.c
src/backend/nodes/makefuncs.c
src/backend/nodes/outfuncs.c
src/backend/optimizer/path/indxpath.c
src/backend/optimizer/plan/createplan.c
src/backend/optimizer/plan/initsplan.c
src/backend/optimizer/plan/subselect.c
src/backend/optimizer/prep/preptlist.c
src/backend/optimizer/util/clauses.c
src/backend/optimizer/util/plancat.c
src/backend/parser/analyze.c
src/backend/parser/parse_agg.c
src/backend/parser/parse_clause.c
src/backend/parser/parse_coerce.c
src/backend/parser/parse_expr.c
src/backend/parser/parse_func.c
src/backend/parser/parse_node.c
src/backend/parser/parse_oper.c
src/backend/parser/parse_type.c
src/backend/rewrite/rewriteManip.c
src/backend/rewrite/rewriteRemove.c
src/backend/rewrite/rewriteSupport.c
src/backend/tcop/fastpath.c
src/backend/tcop/utility.c
src/backend/utils/adt/acl.c
src/backend/utils/adt/arrayfuncs.c
src/backend/utils/adt/format_type.c
src/backend/utils/adt/regproc.c
src/backend/utils/adt/ri_triggers.c
src/backend/utils/adt/ruleutils.c
src/backend/utils/adt/selfuncs.c
src/backend/utils/adt/sets.c
src/backend/utils/cache/catcache.c
src/backend/utils/cache/lsyscache.c
src/backend/utils/cache/syscache.c
src/backend/utils/cache/temprel.c
src/backend/utils/fmgr/dfmgr.c
src/backend/utils/fmgr/fmgr.c
src/backend/utils/init/miscinit.c
src/backend/utils/init/postinit.c
src/backend/utils/misc/superuser.c
src/backend/utils/sort/tuplesort.c
src/include/executor/hashjoin.h
src/include/lib/dllist.h
src/include/nodes/makefuncs.h
src/include/parser/parse_oper.h
src/include/parser/parse_type.h
src/include/rewrite/rewriteSupport.h
src/include/utils/catcache.h
src/include/utils/lsyscache.h
src/include/utils/syscache.h
src/pl/plperl/plperl.c
src/pl/plpgsql/src/pl_comp.c
src/pl/plpgsql/src/pl_exec.c
src/pl/tcl/pltcl.c

index c480f7dfc70982ddb95c4db4125cd1043bc38a8b..653979ada866b0a5cf3eb506225e4f8ffcd3ad3e 100644 (file)
  * either version 2, or (at your option) any later version.
  */
 
+#include "postgres.h"
+
 #include <ctype.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <string.h>
 
-#include "postgres.h"
-#include "miscadmin.h"
 #include "access/xact.h"
 #include "fmgr.h"
-#include "catalog/pg_type.h"
+#include "miscadmin.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
 #include "utils/memutils.h"
-#include "utils/syscache.h"
+#include "utils/lsyscache.h"
 
 #include "array_iterator.h"
 
+
 static int32
 array_iterator(Oid elemtype, Oid proc, int and, ArrayType *array, Datum value)
 {
-       HeapTuple       typ_tuple;
-       Form_pg_type typ_struct;
+       int16           typlen;
        bool            typbyval;
-       int                     typlen;
        int                     nitems,
                                i;
        Datum           result;
@@ -66,16 +65,7 @@ array_iterator(Oid elemtype, Oid proc, int and, ArrayType *array, Datum value)
        }
 
        /* Lookup element type information */
-       typ_tuple = SearchSysCacheTuple(TYPEOID, ObjectIdGetDatum(elemtype),
-                                                                       0, 0, 0);
-       if (!HeapTupleIsValid(typ_tuple))
-       {
-               elog(ERROR, "array_iterator: cache lookup failed for type %u", elemtype);
-               return 0;
-       }
-       typ_struct = (Form_pg_type) GETSTRUCT(typ_tuple);
-       typlen = typ_struct->typlen;
-       typbyval = typ_struct->typbyval;
+       get_typlenbyval(elemtype, &typlen, &typbyval);
 
        /* Lookup the function entry point */
        fmgr_info(proc, &finfo);
index e8f046d0fa529a238cd6863f7bb213606ed6f2e8..bb14d5f49ac5cd2d59e28129cd5a78e5f5c6ad87 100644 (file)
@@ -311,7 +311,7 @@ c-mode)
   9) How do I efficiently access information in tables from the backend code?
   
    You first need to find the tuples(rows) you are interested in. There
-   are two ways. First, SearchSysCacheTuple() and related functions allow
+   are two ways. First, SearchSysCache() and related functions allow
    you to query the system catalogs. This is the preferred way to access
    system tables, because the first call to the cache loads the needed
    rows, and future requests can return the results without accessing the
@@ -321,14 +321,13 @@ c-mode)
    src/backend/utils/cache/lsyscache.c contains many column-specific
    cache lookup functions.
    
-   The rows returned are cached-owned versions of the heap rows. They are
-   invalidated when the base table changes. Because the cache is local to
-   each backend, you may use the pointer returned from the cache for
-   short periods without making a copy of the tuple. If you send the
-   pointer into a large function that will be doing its own cache
-   lookups, it is possible the cache entry may be flushed, so you should
-   use SearchSysCacheTupleCopy() in these cases, and pfree() the tuple
-   when you are done.
+   The rows returned are cache-owned versions of the heap rows.  Therefore,
+   you must not modify or delete the tuple returned by SearchSysCache().
+   What you *should* do is release it with ReleaseSysCache() when you are
+   done using it; this informs the cache that it can discard that tuple
+   if necessary.  If you neglect to call ReleaseSysCache(), then the cache
+   entry will remain locked in the cache until end of transaction, which is
+   tolerable but not very desirable.
    
    If you can't use the system cache, you will need to retrieve the data
    directly from the heap table, using the buffer cache that is shared by
@@ -344,7 +343,9 @@ c-mode)
    You can also use heap_fetch() to fetch rows by block number/offset.
    While scans automatically lock/unlock rows from the buffer cache, with
    heap_fetch(), you must pass a Buffer pointer, and ReleaseBuffer() it
-   when completed. Once you have the row, you can get data that is common
+   when completed.
+
+   Once you have the row, you can get data that is common
    to all tuples, like t_self and t_oid, by merely accessing the
    HeapTuple structure entries. If you need a table-specific column, you
    should take the HeapTuple pointer, and use the GETSTRUCT() macro to
@@ -355,15 +356,16 @@ c-mode)
 
         ((Form_pg_class) GETSTRUCT(tuple))->relnatts
 
-   You should not directly change live tuples in this way. The best way
-   is to use heap_tuplemodify() and pass it your palloc'ed tuple, and the
-   values you want changed. It returns another palloc'ed tuple, which you
+   You must not directly change live tuples in this way. The best way
+   is to use heap_modifytuple() and pass it your original tuple, and the
+   values you want changed. It returns a palloc'ed tuple, which you
    pass to heap_replace(). You can delete tuples by passing the tuple's
-   t_self to heap_destroy(). You can use it for heap_update() too.
-   Remember, tuples can be either system cache versions, which may go
-   away soon after you get them, buffer cache versions, which go away
-   when you heap_getnext(), heap_endscan, or ReleaseBuffer(), in the
-   heap_fetch() case. Or it may be a palloc'ed tuple, that you must
+   t_self to heap_destroy(). You use t_self for heap_update() too.
+
+   Remember, tuples can be either system cache copies, which may go away
+   after you call ReleaseSysCache(), or read directly from disk buffers,
+   which go away when you heap_getnext(), heap_endscan, or ReleaseBuffer(),
+   in the heap_fetch() case. Or it may be a palloc'ed tuple, that you must
    pfree() when finished.
    
   10) What is elog()?
index e62d0c3533acdb21b0b6b93688a6946236b5626b..3c1433d345b33deb41e4c5a5a00001313667dca3 100644 (file)
@@ -358,7 +358,7 @@ cases where Name and char * are used interchangeably.<P>
 tables from the backend code?</H3><P>
 
 You first need to find the tuples(rows) you are interested in.  There
-are two ways.  First, <I>SearchSysCacheTuple()</I> and related functions
+are two ways.  First, <I>SearchSysCache()</I> and related functions
 allow you to query the system catalogs.  This is the preferred way to
 access system tables, because the first call to the cache loads the
 needed rows, and future requests can return the results without
@@ -367,15 +367,14 @@ to look up tuples.  A list of available caches is located in
 <I>src/backend/utils/cache/syscache.c.</I> 
 <I>src/backend/utils/cache/lsyscache.c</I> contains many column-specific
 cache lookup functions.<P>
-
-The rows returned are cached-owned versions of the heap rows.  They are
-invalidated when the base table changes.   Because the cache is local to
-each backend, you may use the pointer returned from the cache for short
-periods without making a copy of the tuple.  If you send the pointer
-into a large function that will be doing its own cache lookups, it is
-possible the cache entry may be flushed, so you should use
-<I>SearchSysCacheTupleCopy()</I> in these cases, and <I>pfree()</I> the
-tuple when you are done.<P>
+   
+The rows returned are cache-owned versions of the heap rows.  Therefore, you
+must not modify or delete the tuple returned by <I>SearchSysCache()</I>.  What
+you <I>should</I> do is release it with <I>ReleaseSysCache()</I> when you are
+done using it; this informs the cache that it can discard that tuple if
+necessary.  If you neglect to call <I>ReleaseSysCache()</I>, then the cache
+entry will remain locked in the cache until end of transaction, which is
+tolerable but not very desirable.<P>
 
 If you can't use the system cache, you will need to retrieve the data
 directly from the heap table, using the buffer cache that is shared by
@@ -392,12 +391,11 @@ and only the valid rows returned.<P>
 You can also use <I>heap_fetch()</I> to fetch rows by block
 number/offset.  While scans automatically lock/unlock rows from the
 buffer cache, with <I>heap_fetch(),</I> you must pass a <I>Buffer</I>
-pointer, and <I>ReleaseBuffer()</I> it when completed.
+pointer, and <I>ReleaseBuffer()</I> it when completed.<P>
 
 Once you have the row, you can get data that is common to all tuples,
 like <I>t_self</I> and <I>t_oid,</I> by merely accessing the
 <I>HeapTuple</I> structure entries.
-
 If you need a table-specific column, you should take the HeapTuple
 pointer, and use the <I>GETSTRUCT()</I> macro to access the
 table-specific start of the tuple.  You then cast the pointer as a
@@ -411,18 +409,18 @@ the columns by using a structure pointer:
 </CODE>
 </PRE>
 
-You should not directly change <I>live</I> tuples in this way.  The best
-way is to use <I>heap_tuplemodify()</I> and pass it your palloc'ed
-tuple, and the values you want changed.  It returns another palloc'ed
+You must not directly change <I>live</I> tuples in this way.  The best
+way is to use <I>heap_modifytuple()</I> and pass it your original
+tuple, and the values you want changed.  It returns a palloc'ed
 tuple, which you pass to <I>heap_replace().</I>
 
 You can delete tuples by passing the tuple's <I>t_self</I> to
-<I>heap_destroy().</I>  You can use it for <I>heap_update()</I> too.
+<I>heap_destroy().</I>  You use <I>t_self</I> for <I>heap_update()</I> too.
 
-Remember, tuples can be either system cache versions, which may go away
-soon after you get them, buffer cache versions, which go away when
-you <I>heap_getnext(),</I> <I>heap_endscan,</I> or
-<I>ReleaseBuffer()</I>, in the <I>heap_fetch()</I> case.  Or it may be a
+Remember, tuples can be either system cache copies, which may go away after
+you call <I>ReleaseSysCache()</I>, or read directly from disk buffers, which
+go away when you <I>heap_getnext()</I>, <I>heap_endscan</I>, or
+<I>ReleaseBuffer()</I>, in the <I>heap_fetch()</I> case. Or it may be a
 palloc'ed tuple, that you must <I>pfree()</I> when finished.
 
 <H3><a name="10">10</a>)       What is elog()?</H3><P>
index e00b3b211b861b7bfb250b811aba911017043cb2..33b6212b25b06a9f86f056401532324becb73841 100644 (file)
@@ -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);
 }
 
 /* ----------------
index a4fa19e8b32f654a1939ba4a9cd0f525bf261517..c17921e3ad8bb517fefb14e4f89f6cba86dc8480 100644 (file)
@@ -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))
                {
                        /* ----------------
index 62f46879a8c7d273b31dda50a00550f8cf77b041..eaea06b774e3eeaead0905ad60333c555448f1fb 100644 (file)
@@ -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;
 }
 
 
index d281ee615f027aa721360cb8dc942aa696a1116a..02004582a920d0dfcfb4020b1e576321ab4332f5 100644 (file)
@@ -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));
index d20a94278049429da65a922960912a6928629190..d84b47a4fb1231913064174aada39eeaad152b49 100644 (file)
@@ -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();
 
index 60f855784d64a0d75a122af5af208318c3ce2f0b..cc30a1039415b94977e3595c37df571b5de8c1a8 100644 (file)
@@ -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;
 }
index d2a390579d95fe94b475f6e2ae30f8384cfd84e1..dd32ca7df6343bd9bb7309f9e9fac7042ac907a2 100644 (file)
@@ -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++;
        }
 }
index 9ca3467b6de7f823498967059ffa5bb6cfaf6c1d..87120882ca60a3b50fdc19ae12b7e5adc03ed365 100644 (file)
@@ -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
index c7642d2fbfe0547c8385d15b2b7a303b5ce52ebb..9b8f7b1363b254f5707c38ed34ddfbc0e6d272dd 100644 (file)
@@ -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);
index a651a7270b08baa9082e60aebd2765bbd46ecca8..f98cc3ee342ecdc595f5f698d08b028726fdfc4b 100644 (file)
@@ -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,
index 3b7587279d02c2a2db0b50287f8dfed83ebf26c7..8896950f93c7fbab08936d69e97be908abddbac8 100644 (file)
@@ -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),
index 4ddbf4653f8b7f122b11919843ca547650482abc..7834ead16ae2672cc1823b57bdd5555a4dc07893 100644 (file)
@@ -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);
index 493f2a86c682914ebfa56b4e927339c30d0ea873..d988570b4b9c01a9eae9bfc47a6dbff8a2a33444 100644 (file)
@@ -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);
 }
index 9d0c39da41d93d100828186e012eb17534df657f..bc35b07999da4d3cd098ba466aeead638cb48785 100644 (file)
@@ -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);
 }
 
index df062554a7271c6f5ccbb7d88afa1687a79afe8b..e5425045926a9f2eb535e5988c484d7204a2276d 100644 (file)
@@ -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
                {
index 10991ff97ce0a4843862122088eb4ce9932b22e8..4bcc5bc88341609035f3225753a5aa0774fa663b 100644 (file)
@@ -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);
 
        /*
index 05eec1561520199385e8231a3c93488f0d18266f..1f222c0dfcdc0a4cc33fa3dc790239a2d00c7de9 100644 (file)
@@ -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);
 }
index fe548802fb227a999e9a1f2014aa22ff390865e4..fdaa711310fa8f05e47d88f4f81c3a82b172ea8e 100644 (file)
@@ -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:
index bff2b897c6e0fe0073964d5cac673aecaf03f12e..8ab997831b9dcc265f6ccc7436cf772a53ed6904 100644 (file)
@@ -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);
index 87e8109a7b0f98cf98d10cd51cd65573148015ab..f96fc3de4f5e330fc901c28eb86babddcd186612 100644 (file)
@@ -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;
 }
 
 
index b610b8150db573b54a55884d1e6007adc45df47f..bc8dd895f5878c47b085f347879bd2c100cd24c0 100644 (file)
@@ -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);
+}
index f9a02fa3e03b96cb3988bdea91ed16d58493a30a..0bb4caa53441c979719bdfbd643bb8d976021267 100644 (file)
@@ -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;
 }
 
index 4f8555c52c57044753df5aa3fe690ff926713b32..f026e3ce3a532814421aa48c8c823dbfcdcc5410 100644 (file)
@@ -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);
        }
 
        /*
index 01fe7b6adff6e7f200baafac9db51a2a42cca6bc..b2e1ed02ec5dc4dd22780eb8a4992668c1c3bd4b 100644 (file)
@@ -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);
 }
 
 /*
index ec8aec7005f169e3df795090322a658d2403293d..5d4d3f09bf7df833f45af74b529f31de088c4743 100644 (file)
@@ -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);
 
index a45b9795c24513538ad193b743b85fb050cf74f3..39490bb36d6119e03473a820b1edb73f4fa9e3b2 100644 (file)
@@ -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);
 }
index 32c024b11fa1781bb2f21c34a21d90dd28bd7450..5f5c3e361407ba5780a0f69ecf60eb68ed5fa476 100644 (file)
@@ -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);
index 39991689dd8be1e90c5c083a484794deb5934fe1..e57d7912c95bd0693ff309b7a2011a20d9f814bb 100644 (file)
@@ -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));
index a431ac8844059ffe71f3670c259e49d80e068bda..5deda2e8e68794e576a3ebc7f38a75ff2db13f54 100644 (file)
@@ -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);
 }
 
 
index 31855a912427e6ccb241b847487c6d77f6056a05..c4fb5a86b6c9b01367f10ea912cdc01044a519c3 100644 (file)
@@ -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;
index 13c2ecf1676d968bdeab5a0e6b6b59daedd4dfa0..838a580d5293a0a4b9e238bbb57eda46b31bc04d 100644 (file)
@@ -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++;
index 1752a096a20326810228b380c35b2837034bd42f..8ac29221eeaee5f19affa7c3b4cd55506ef41ab9 100644 (file)
@@ -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;
 }
index dcf8b871905c103faca4dff7c2acdb15d9abffec..0de7f5ab07457255d323263e539fa12db41df996 100644 (file)
@@ -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;
index 462df89e9cbf7ce45eb13ec6c31796a9203ee7d4..652058bedcb7bdb58aae68e1f5cb3eb0afa90ee3 100644 (file)
@@ -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;
index 781fc1d4b5786c2a0830dcf167173b6eaa2d4015..63a7f50d1d632cc209e02ed7969c4e3f4aad931d 100644 (file)
@@ -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;
        }
 
index 765ccbd484150b61e92a488de06b4ec945fec4b3..fc416d5defa3b1cb7e4a43cbda7076822b06e371 100644 (file)
@@ -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;
index 9621168d142cb347493bc10e24d600f1577b433a..e9d7cbd554d96384a695bee84c80d249cf8a34ae 100644 (file)
@@ -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
index d98eb27ead6b06a9064d2e7491d12942833b1f9a..391aec45568829bc35687044babb5b5a02319b21 100644 (file)
@@ -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
@@ -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;
        }
index df7f96c703f871664be1a1bc65476b4b4ddee5e7..8f814fc41ea6c5b4de1f0e522d9a246576de213f 100644 (file)
  *       Andrew Yu                     Oct 20, 1994    file creation
  */
 #include "postgres.h"
+
 #include "nodes/makefuncs.h"
+#include "utils/lsyscache.h"
+
 
 /*
  * makeOper -
@@ -143,6 +146,26 @@ makeConst(Oid consttype,
        return cnst;
 }
 
+/*
+ * 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
index 4a82079903d206d27f9d5e7a191e9a42f618f8d7..b5df665f8b9b4eee67d0131cfd0763c2cec5bf58 100644 (file)
@@ -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)
index 2d84818b95ee0c1a27a33d06cae08b3774cf55ca..38a23394efe902ae4f47ae510667db37a59534c7 100644 (file)
@@ -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'));
 }
 
 /*
index e05894166df3160deee7e6952fdfc170a5b4b84e..9d2327b9ede27d068f0327ddcf8a741efcb77baf 100644 (file)
@@ -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;
index 905bebd2c86207a4ede4a5db093a685561afb99d..5c2aa2ac34a5d6f0a58699f46d98abf5408ff032 100644 (file)
@@ -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-
index c36bb3a81d3432fa3c67b21ba9a95c9e3bb47290..8076ba0a241a988732a24bc640721740bf452dab 100644 (file)
@@ -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,
index 1e7c5adee3b332353b9ec8717a37e30f93fa9fa7..22cd80f527dfe77509eade0979ac2bf691b88503 100644 (file)
@@ -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,
index 4c8b9f8c2fd7d0be8d618d2bdbdc546306635a44..94ade6c59867e99b4302fc04747f1948688e6c41 100644 (file)
@@ -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()
index 54bed98c4070b739827affcac164ddf16dbe648c..e7881580f105b05b82ba2341717514166fdc114d 100644 (file)
@@ -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;
 }
index de7c5d9f643614fc049a2c056a61847e082c0da9..ee606f99a01a68e6274de013552870e1eda2ece3 100644 (file)
@@ -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);
 }
index a5686e7c8fbfa716aa431a99bfe2162be74cd121..26d9e58a0a20b27d3fe8fb73c4ffa825dc720c61 100644 (file)
@@ -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;
index 4784d6c32652a4c84f4946badb7337495a1c8cd9..dc3bb70b95a6607ec63c2ea84f9b9a719b488166 100644 (file)
@@ -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);
 
index fb515432f06478c50e7173068b7c4c2541be65a6..a0e25f72476d302cc680b05117ff164990c33768 100644 (file)
@@ -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);
index e3886993519669b03a4bbe5f4d1b27ccffc31dac..6e6fc362aa8e7d1a07a8e04cfe5f478934cffc8e 100644 (file)
@@ -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 */
index 7cadd0c2ea2b3e71df96fdd900187165bf9a2475..32f5811ea91eb1e2e0fba7edc00ee8edcb797d33 100644 (file)
@@ -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;
                }
index 763affcde02e321eab9debb5775571e58b295c88..4cc38eb671c3f12f65ef4a7ba96e754966d4ecc1 100644 (file)
@@ -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;
 }
 
index ef29f945736db502cdf8f8531b9c649db618f869..d43c3633cc714ebb19982f38ac806c2ff84027e1 100644 (file)
@@ -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));
 }
index 6af9401b208e27716715497329d4a621a529fa74..abf0e40e7b4f025d3c7717bb06d025209f4fa727 100644 (file)
 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
index cf2b156565b693d0ed7dd5dfff9efafeddc26f2f..68c390683f26dfb81fb4267eaeb27f5d4ee13b71 100644 (file)
@@ -13,6 +13,7 @@
  */
 #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);
 
index 814daa401896df0ccee95893819e0920cf04d69b..1018bdfec2311d1929226ea1df155a9692e9e4a7 100644 (file)
@@ -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
index 0b840a5b89607d614f8bdafda67812deac75edb2..d3379f6f4be63c4902218e7c04904e4f08cc2a6d 100644 (file)
 #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;
index 7cae9028b68d89a02e3c5bd064d4bab6f2a64681..57b230c85f7cc9b8025c5df09dea9ec08873c8ef 100644 (file)
@@ -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!
         */
index 9240a5972b6495832370b3b26b1d073cf29959d7..16b175ab71920a3408337a7a015ab44a231d4e3e 100644 (file)
@@ -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);
 }
 
 
index d43560db4b5b6705c86ae1b2883f57dd465614a2..095027c8d29b9c98d6dceab26d2773ead0bd2b49 100644 (file)
@@ -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 ");
index 5560d384676763d93828217937eabbea1e0cadf0..67e22459d4c5ef485044926859acd95bd88b7834 100644 (file)
@@ -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);
 }
 
 /*
index f485beeba88602ac427982a5116f5a003b44159a..259264e8656d9a9302725e610171846776d5e02c 100644 (file)
@@ -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;
 }
 
index 26a027205afd5e3db1d1b41fe0e412af9e8592e4..24552987cd569c1495a9c2196632c346ef381482 100644 (file)
@@ -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
                {
index f801117773039fc04f688f18e0b4f6f54670cf5e..7b7915c7f2f1bde0edde44bb26abbfd76a8b0b6d 100644 (file)
@@ -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);
        }
 
        /* ----------
index 2d0f95ba4ba88ecdd8e12254dce3e66c9c8f7aa6..0ef7ac0098c4626e1713abe405eb41c825fb652e 100644 (file)
@@ -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;
 }
 
 
index d111532c66e677b653a646af9cc5c5c419fd1c75..f83440b15d822d3d4e3b76372abe395c7a7641f4 100644 (file)
@@ -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'));
 }
 
 /*
index 0b724d52261ea4611976fe4cad89beab61dc04eb..b80877c9f446195722cd9ba8a779a69ffb11c1ee 100644 (file)
@@ -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;
 }
 
index 289265b0c48be75d4e23da5d7972fd216578c723..839801c455978fb75f24970acaeee6d773010271 100644 (file)
@@ -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);
+       }
 }
 
 /* --------------------------------
index 8a5b7a9790bfa2202ea1461391b1668d46960958..d55b1b2dbc69eff2d5287bc6373e2ceff5536d09 100644 (file)
 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';
index 9bc6291c7707f7d543673d80a5e58eb5446b6d6d..9ffe67ed4f9b7fc22f66a9e1a1b9684f85eade26 100644 (file)
@@ -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
index f7d70965d97b26496148ce8519d87963fc55313f..cbdecfd639bb44c9d3f6dda75948b8f6bce28429 100644 (file)
@@ -34,7 +34,6 @@
 #include "catalog/heap.h"
 #include "catalog/index.h"
 #include "miscadmin.h"
-#include "utils/catcache.h"
 #include "utils/temprel.h"
 
 
index e589c41cda11dd77a1fec9eecb28558bd8b6d078..2615d63c600ad353e7b6cdaf616616d34040204e 100644 (file)
@@ -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;
 }
 
index 3b5b40b66cf28f75669c40a5da5aa1addc517ae2..fac0d319e75c3a1d0c7d3d99d0e66f09386e605f 100644 (file)
@@ -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);
 }
 
 
index 6eee22f0083a03cc693e97cd6d27dd81de0e6928..0843a6d1214ae9f156a5a19b112fcf46477fa1d6 100644 (file)
@@ -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;
 }
 
 
index 22df20e95b7960392ae50089eb69e6ab286d3e56..9675beba1fdc6f982dadf61428c7c227aaa6c93e 100644 (file)
@@ -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
         */
index c7eb86c0ac95e0c7334c3d614a73298725daa6b8..75f439339916ee073d4101d50d999f3e913a0f83 100644 (file)
@@ -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;
 }
index 2e4eced63b5cb293a5cf9cc7250b33a7ac59b1c3..c121ff6257a0684495432d1d2867508046ffda08 100644 (file)
@@ -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;
 }
index fdc89f93f1058f9b2bf1cd7c8f74c54a2d6912b6..c349eaf98a17cd0feca95f844ad3e8371eee7e6c 100644 (file)
@@ -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
index 08146a936aba56cd93bb058ef5f82f08c959dcb4..103e6563ea4db44c5d0a0806318affc4b51703f4 100644 (file)
@@ -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;
  *      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
  *
@@ -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 */
index 0637b28f0ce24b8e340dfcc2b06eccabe4f48f8a..1507bef00cd88266fbc1789d5ec2ae3ae5ff2631 100644 (file)
@@ -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 */
index c2d4f7dc282944341106bb9f6bde0b07e18eb5dd..59607c743fd984942560acaf897fa5683f3600c7 100644 (file)
 
 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 */
index 04c7b55faafa95dc09c5c670eb747df877fe8146..22953ba7f200b2611928950ca8c25998b72835fb 100644 (file)
@@ -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)
 
index cedcd87abdd487d94a0abaa17ea7b3075c30dfd7..372fb20e68803371070ae8618a2ebf73b04f1192 100644 (file)
@@ -14,7 +14,7 @@
 #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);
index a26f62ae73a2ca4a8a87cdee956b20ccdf3cb3a4..8643f9bacf6cca4e8f75b12818c7d8af16840040 100644 (file)
 
 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);
index db923df069b95584b515605ab92c1e1e7d140a98..c2619aa3c4e4eb355c33e83dd48b4f380c3e52cc 100644 (file)
@@ -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 */
index f970adc35e08a23169c43525d6131b26fc87c4ee..39187608dfe0afa5a72f972d78e97784c4b12d25 100644 (file)
 #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);
 
index 9b289c0c96742e33868c21fd963eaf6a65e90703..d853e27d59b59d3ea54dededed537c14f063b09f 100644 (file)
@@ -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
index c0858822cbc27f5195628aa4e81fe79b9d4d2cb6..d29bb16d8496fd57588d91379ce27b5f4aa3dd22 100644 (file)
@@ -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
         * ----------
index 0e10486cd3e24754f04e9da5d0ecc16fd2335324..99956d1ecdeaca9e966feb1f93df5031d7b29015 100644 (file)
@@ -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);
                }
        }
 
index f27bb23b4182ba08e748514bb5ddbed3d0b1cc93..450916ceb401f873d15012dea341b7fe4dc83041 100644 (file)
@@ -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