]> granicus.if.org Git - postgresql/commitdiff
Mega-commit to make heap_open/heap_openr/heap_close take an
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 18 Sep 1999 19:08:25 +0000 (19:08 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 18 Sep 1999 19:08:25 +0000 (19:08 +0000)
additional argument specifying the kind of lock to acquire/release (or
'NoLock' to do no lock processing).  Ensure that all relations are locked
with some appropriate lock level before being examined --- this ensures
that relevant shared-inval messages have been processed and should prevent
problems caused by concurrent VACUUM.  Fix several bugs having to do with
mismatched increment/decrement of relation ref count and mismatched
heap_open/close (which amounts to the same thing).  A bogus ref count on
a relation doesn't matter much *unless* a SI Inval message happens to
arrive at the wrong time, which is probably why we got away with this
sloppiness for so long.  Repair missing grab of AccessExclusiveLock in
DROP TABLE, ALTER/RENAME TABLE, etc, as noted by Hiroshi.
Recommend 'make clean all' after pulling this update; I modified the
Relation struct layout slightly.
Will post further discussion to pghackers list shortly.

70 files changed:
contrib/miscutil/misc_utils.c
src/backend/access/gist/gist.c
src/backend/access/hash/hash.c
src/backend/access/heap/heapam.c
src/backend/access/index/indexam.c
src/backend/access/index/istrat.c
src/backend/access/nbtree/nbtree.c
src/backend/access/rtree/rtree.c
src/backend/access/transam/transam.c
src/backend/access/transam/varsup.c
src/backend/bootstrap/bootstrap.c
src/backend/catalog/aclchk.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/async.c
src/backend/commands/cluster.c
src/backend/commands/command.c
src/backend/commands/copy.c
src/backend/commands/creatinh.c
src/backend/commands/dbcommands.c
src/backend/commands/explain.c
src/backend/commands/indexcmds.c
src/backend/commands/proclang.c
src/backend/commands/remove.c
src/backend/commands/rename.c
src/backend/commands/sequence.c
src/backend/commands/trigger.c
src/backend/commands/user.c
src/backend/commands/vacuum.c
src/backend/executor/execAmi.c
src/backend/executor/execMain.c
src/backend/executor/execUtils.c
src/backend/executor/nodeAppend.c
src/backend/optimizer/path/indxpath.c
src/backend/optimizer/plan/planner.c
src/backend/optimizer/util/plancat.c
src/backend/parser/analyze.c
src/backend/parser/parse_clause.c
src/backend/parser/parse_func.c
src/backend/parser/parse_oper.c
src/backend/parser/parse_relation.c
src/backend/rewrite/locks.c
src/backend/rewrite/rewriteDefine.c
src/backend/rewrite/rewriteHandler.c
src/backend/rewrite/rewriteRemove.c
src/backend/rewrite/rewriteSupport.c
src/backend/storage/buffer/bufmgr.c
src/backend/storage/buffer/localbuf.c
src/backend/storage/large_object/inv_api.c
src/backend/storage/lmgr/lmgr.c
src/backend/storage/lmgr/lock.c
src/backend/tcop/utility.c
src/backend/utils/adt/not_in.c
src/backend/utils/adt/regproc.c
src/backend/utils/adt/selfuncs.c
src/backend/utils/adt/sets.c
src/backend/utils/cache/catcache.c
src/backend/utils/cache/relcache.c
src/backend/utils/cache/syscache.c
src/backend/utils/fmgr/dfmgr.c
src/backend/utils/misc/database.c
src/include/access/heapam.h
src/include/storage/buf_internals.h
src/include/storage/lmgr.h
src/include/utils/rel.h

index 75184439717c37eb42f006a62794a73b3136abee..d9237bd9dbba10c4e478877a16306c2501406247 100644 (file)
@@ -89,9 +89,8 @@ active_listeners(text *relname)
        int                     ourpid = getpid();
        char            listen_name[NAMEDATALEN];
 
-       lRel = heap_openr(ListenerRelationName);
+       lRel = heap_openr(ListenerRelationName, AccessShareLock);
        tdesc = RelationGetDescr(lRel);
-       LockRelation(lRel, AccessShareLock);
 
        if (relname && (VARSIZE(relname) > VARHDRSZ)) {
                len = MIN(VARSIZE(relname)-VARHDRSZ, NAMEDATALEN-1);
@@ -110,19 +109,14 @@ active_listeners(text *relname)
        {
                d = heap_getattr(lTuple, Anum_pg_listener_pid, tdesc, &isnull);
                pid = DatumGetInt32(d);
-#ifdef HAVE_KILL
                if ((pid == ourpid) || (kill(pid, SIGTSTP) == 0)) {
                        /* elog(NOTICE, "%d ok", pid); */
                        count++;
                }
-#else
-               count++;
-#endif
        }
        heap_endscan(sRel);
 
-       UnlockRelation(lRel, AccessShareLock);
-       heap_close(lRel);
+       heap_close(lRel, AccessShareLock);
 
        return count;
 }
index 3211134742362f54af412aa1ddca2750317b70b5..0535fd6278db7d52c4ab2b57e0a6248f7caef76f 100644 (file)
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.44 1999/07/19 02:06:15 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.45 1999/09/18 19:05:46 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,6 +20,7 @@
 #include "catalog/index.h"
 #include "catalog/pg_index.h"
 #include "executor/executor.h"
+#include "miscadmin.h"
 #include "utils/syscache.h"
 
 
@@ -88,8 +89,6 @@ gistbuild(Relation heap,
        TupleTableSlot *slot;
 
 #endif
-       Oid                     hrelid,
-                               irelid;
        Node       *pred,
                           *oldPred;
        GISTSTATE       giststate;
@@ -271,28 +270,31 @@ gistbuild(Relation heap,
        }
 
        /*
-        * Since we just inted the tuples in the heap, we update its stats in
-        * pg_relation to guarantee that the planner takes advantage of the
-        * index we just created.  UpdateStats() does a
-        * CommandinterIncrement(), which flushes changed entries from the
-        * system relcache.  The act of constructing an index changes these
-        * heap and index tuples in the system catalogs, so they need to be
-        * flushed.  We close them to guarantee that they will be.
+        * Since we just counted the tuples in the heap, we update its stats
+        * in pg_class to guarantee that the planner takes advantage of the
+        * index we just created.  But, only update statistics during
+        * normal index definitions, not for indices on system catalogs
+        * created during bootstrap processing.  We must close the relations
+        * before updating statistics to guarantee that the relcache entries
+        * are flushed when we increment the command counter in UpdateStats().
+        * But we do not release any locks on the relations; those will be
+        * held until end of transaction.
         */
-
-       hrelid = RelationGetRelid(heap);
-       irelid = RelationGetRelid(index);
-       heap_close(heap);
-       index_close(index);
-
-       UpdateStats(hrelid, nh, true);
-       UpdateStats(irelid, ni, false);
-
-       if (oldPred != NULL)
+       if (IsNormalProcessingMode())
        {
-               if (ni == nh)
-                       pred = NULL;
-               UpdateIndexPredicate(irelid, oldPred, pred);
+               Oid             hrelid = RelationGetRelid(heap);
+               Oid             irelid = RelationGetRelid(index);
+
+               heap_close(heap, NoLock);
+               index_close(index);
+               UpdateStats(hrelid, nh, true);
+               UpdateStats(irelid, ni, false);
+               if (oldPred != NULL)
+               {
+                       if (ni == nh)
+                               pred = NULL;
+                       UpdateIndexPredicate(irelid, oldPred, pred);
+               }
        }
 
        /* be tidy */
index 1130367b65de3c057ec8ca2566ab9447cbe4bc02..6e729008e85b70abea3200becb47eb6672458076 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.30 1999/07/17 20:16:38 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.31 1999/09/18 19:05:52 tgl Exp $
  *
  * NOTES
  *       This file contains only the public interface routines.
@@ -66,8 +66,6 @@ hashbuild(Relation heap,
        TupleTableSlot *slot;
 
 #endif
-       Oid                     hrelid,
-                               irelid;
        Node       *pred,
                           *oldPred;
 
@@ -232,17 +230,20 @@ hashbuild(Relation heap,
        /*
         * Since we just counted the tuples in the heap, we update its stats
         * in pg_class to guarantee that the planner takes advantage of the
-        * index we just created. Finally, only update statistics during
+        * index we just created.  But, only update statistics during
         * normal index definitions, not for indices on system catalogs
         * created during bootstrap processing.  We must close the relations
-        * before updatings statistics to guarantee that the relcache entries
+        * before updating statistics to guarantee that the relcache entries
         * are flushed when we increment the command counter in UpdateStats().
+        * But we do not release any locks on the relations; those will be
+        * held until end of transaction.
         */
        if (IsNormalProcessingMode())
        {
-               hrelid = RelationGetRelid(heap);
-               irelid = RelationGetRelid(index);
-               heap_close(heap);
+               Oid             hrelid = RelationGetRelid(heap);
+               Oid             irelid = RelationGetRelid(index);
+
+               heap_close(heap, NoLock);
                index_close(index);
                UpdateStats(hrelid, nhtups, true);
                UpdateStats(irelid, nitups, false);
index d8dc24c41f0a4502f04f00c879a6ab7b1e88a5d5..092a23cc0ec8dc48cffe013af73a0c840d7c5d3d 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.53 1999/07/19 07:07:18 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.54 1999/09/18 19:05:58 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -486,15 +486,20 @@ heapgettup(Relation relation,
 /* ----------------
  *             heap_open - open a heap relation by relationId
  *
- *             presently the relcache routines do all the work we need
- *             to open/close heap relations.
+ *             If lockmode is "NoLock", no lock is obtained on the relation,
+ *             and the caller must check for a NULL return value indicating
+ *             that no such relation exists.
+ *             Otherwise, an error is raised if the relation does not exist,
+ *             and the specified kind of lock is obtained on the relation.
  * ----------------
  */
 Relation
-heap_open(Oid relationId)
+heap_open(Oid relationId, LOCKMODE lockmode)
 {
        Relation        r;
 
+       Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
+
        /* ----------------
         *      increment access statistics
         * ----------------
@@ -502,26 +507,41 @@ heap_open(Oid relationId)
        IncrHeapAccessStat(local_open);
        IncrHeapAccessStat(global_open);
 
-       r = (Relation) RelationIdGetRelation(relationId);
+       /* The relcache does all the real work... */
+       r = RelationIdGetRelation(relationId);
 
+       /* Under no circumstances will we return an index as a relation. */
        if (RelationIsValid(r) && r->rd_rel->relkind == RELKIND_INDEX)
                elog(ERROR, "%s is an index relation", r->rd_rel->relname.data);
 
+       if (lockmode == NoLock)
+               return r;                               /* caller must check RelationIsValid! */
+
+       if (! RelationIsValid(r))
+               elog(ERROR, "Relation %u does not exist", relationId);
+
+       LockRelation(r, lockmode);
+
        return r;
 }
 
 /* ----------------
  *             heap_openr - open a heap relation by name
  *
- *             presently the relcache routines do all the work we need
- *             to open/close heap relations.
+ *             If lockmode is "NoLock", no lock is obtained on the relation,
+ *             and the caller must check for a NULL return value indicating
+ *             that no such relation exists.
+ *             Otherwise, an error is raised if the relation does not exist,
+ *             and the specified kind of lock is obtained on the relation.
  * ----------------
  */
 Relation
-heap_openr(char *relationName)
+heap_openr(char *relationName, LOCKMODE lockmode)
 {
        Relation        r;
 
+       Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
+
        /* ----------------
         *      increment access statistics
         * ----------------
@@ -529,24 +549,37 @@ heap_openr(char *relationName)
        IncrHeapAccessStat(local_openr);
        IncrHeapAccessStat(global_openr);
 
+       /* The relcache does all the real work... */
        r = RelationNameGetRelation(relationName);
 
+       /* Under no circumstances will we return an index as a relation. */
        if (RelationIsValid(r) && r->rd_rel->relkind == RELKIND_INDEX)
                elog(ERROR, "%s is an index relation", r->rd_rel->relname.data);
 
+       if (lockmode == NoLock)
+               return r;                               /* caller must check RelationIsValid! */
+
+       if (! RelationIsValid(r))
+               elog(ERROR, "Relation '%s' does not exist", relationName);
+
+       LockRelation(r, lockmode);
+
        return r;
 }
 
 /* ----------------
  *             heap_close - close a heap relation
  *
- *             presently the relcache routines do all the work we need
- *             to open/close heap relations.
+ *             If lockmode is not "NoLock", we first release the specified lock.
+ *             Note that it is often sensible to hold a lock beyond heap_close;
+ *             in that case, the lock is released automatically at xact end.
  * ----------------
  */
 void
-heap_close(Relation relation)
+heap_close(Relation relation, LOCKMODE lockmode)
 {
+       Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
+
        /* ----------------
         *      increment access statistics
         * ----------------
@@ -554,6 +587,10 @@ heap_close(Relation relation)
        IncrHeapAccessStat(local_close);
        IncrHeapAccessStat(global_close);
 
+       if (lockmode != NoLock)
+               UnlockRelation(relation, lockmode);
+
+       /* The relcache does the real work... */
        RelationClose(relation);
 }
 
@@ -582,21 +619,29 @@ heap_beginscan(Relation relation,
         *      sanity checks
         * ----------------
         */
-       if (RelationIsValid(relation) == false)
+       if (! RelationIsValid(relation))
                elog(ERROR, "heap_beginscan: !RelationIsValid(relation)");
 
-       LockRelation(relation, AccessShareLock);
-
-       /* XXX someday assert SelfTimeQual if relkind == RELKIND_UNCATALOGED */
-       if (relation->rd_rel->relkind == RELKIND_UNCATALOGED)
-               snapshot = SnapshotSelf;
-
        /* ----------------
         *      increment relation ref count while scanning relation
         * ----------------
         */
        RelationIncrementReferenceCount(relation);
 
+       /* ----------------
+        *      Acquire AccessShareLock for the duration of the scan
+        *
+        *      Note: we could get an SI inval message here and consequently have
+        *      to rebuild the relcache entry.  The refcount increment above
+        *      ensures that we will rebuild it and not just flush it...
+        * ----------------
+        */
+       LockRelation(relation, AccessShareLock);
+
+       /* XXX someday assert SelfTimeQual if relkind == RELKIND_UNCATALOGED */
+       if (relation->rd_rel->relkind == RELKIND_UNCATALOGED)
+               snapshot = SnapshotSelf;
+
        /* ----------------
         *      allocate and initialize scan descriptor
         * ----------------
@@ -683,15 +728,19 @@ heap_endscan(HeapScanDesc scan)
         */
        unpinscan(scan);
 
+       /* ----------------
+        *      Release AccessShareLock acquired by heap_beginscan()
+        * ----------------
+        */
+       UnlockRelation(scan->rs_rd, AccessShareLock);
+
        /* ----------------
         *      decrement relation reference count and free scan descriptor storage
         * ----------------
         */
        RelationDecrementReferenceCount(scan->rs_rd);
 
-       UnlockRelation(scan->rs_rd, AccessShareLock);
-
-       pfree(scan);                            /* XXX */
+       pfree(scan);
 }
 
 /* ----------------
index 869e5e1e690354b0a9920f38e2be7311487e3361..6ad242c0c39a5cdbb15dd53bda76ff442c5bdcfd 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.35 1999/07/16 04:58:28 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.36 1999/09/18 19:06:04 tgl Exp $
  *
  * INTERFACE ROUTINES
  *             index_open              - open an index relation by relationId
  *             index_open - open an index relation by relationId
  *
  *             presently the relcache routines do all the work we need
- *             to open/close index relations.
+ *             to open/close index relations.  However, callers of index_open
+ *             expect it to succeed, so we need to check for a failure return.
+ *
+ *             Note: we acquire no lock on the index.  An AccessShareLock is
+ *             acquired by index_beginscan (and released by index_endscan).
  * ----------------
  */
 Relation
 index_open(Oid relationId)
 {
-       return RelationIdGetRelation(relationId);
+       Relation        r;
+
+       r = RelationIdGetRelation(relationId);
+
+       if (! RelationIsValid(r))
+               elog(ERROR, "Index %u does not exist", relationId);
+
+       if (r->rd_rel->relkind != RELKIND_INDEX)
+               elog(ERROR, "%s is not an index relation", r->rd_rel->relname.data);
+
+       return r;
 }
 
 /* ----------------
  *             index_openr - open a index relation by name
  *
- *             presently the relcache routines do all the work we need
- *             to open/close index relations.
+ *             As above, but lookup by name instead of OID.
  * ----------------
  */
 Relation
 index_openr(char *relationName)
 {
-       return RelationNameGetRelation(relationName);
+       Relation        r;
+
+       r = RelationNameGetRelation(relationName);
+
+       if (! RelationIsValid(r))
+               elog(ERROR, "Index '%s' does not exist", relationName);
+
+       if (r->rd_rel->relkind != RELKIND_INDEX)
+               elog(ERROR, "%s is not an index relation", r->rd_rel->relname.data);
+
+       return r;
 }
 
 /* ----------------
@@ -223,6 +246,16 @@ index_beginscan(Relation relation,
        RELATION_CHECKS;
        GET_REL_PROCEDURE(beginscan, ambeginscan);
 
+       RelationIncrementReferenceCount(relation);
+
+       /* ----------------
+        *      Acquire AccessShareLock for the duration of the scan
+        *
+        *      Note: we could get an SI inval message here and consequently have
+        *      to rebuild the relcache entry.  The refcount increment above
+        *      ensures that we will rebuild it and not just flush it...
+        * ----------------
+        */
        LockRelation(relation, AccessShareLock);
 
        scandesc = (IndexScanDesc)
@@ -260,7 +293,11 @@ index_endscan(IndexScanDesc scan)
 
        fmgr(procedure, scan);
 
+       /* Release lock and refcount acquired by index_beginscan */
+
        UnlockRelation(scan->relation, AccessShareLock);
+
+       RelationDecrementReferenceCount(scan->relation);
 }
 
 /* ----------------
index 1cdaadbc0c39fb5ec053d21598a7502526793879..cab6e5846091fb20434b094f37d5b8342a225d27 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.35 1999/07/16 04:58:28 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.36 1999/09/18 19:06:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -558,7 +558,7 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
                                                           F_OIDEQ,
                                                           ObjectIdGetDatum(indexObjectId));
 
-               relation = heap_openr(IndexRelationName);
+               relation = heap_openr(IndexRelationName, AccessShareLock);
                scan = heap_beginscan(relation, false, SnapshotNow, 1, entry);
                tuple = heap_getnext(scan, 0);
        }
@@ -591,7 +591,7 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
        if (IsBootstrapProcessingMode())
        {
                heap_endscan(scan);
-               heap_close(relation);
+               heap_close(relation, AccessShareLock);
        }
 
        /* if support routines exist for this access method, load them */
@@ -604,7 +604,8 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
                ScanKeyEntryInitialize(&entry[1], 0, Anum_pg_amproc_amopclaid,
                                                           F_OIDEQ, 0);
 
-               relation = heap_openr(AccessMethodProcedureRelationName);
+               relation = heap_openr(AccessMethodProcedureRelationName,
+                                                         AccessShareLock);
 
                for (attributeNumber = 1; attributeNumber <= maxAttributeNumber;
                         attributeNumber++)
@@ -631,7 +632,7 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
 
                        heap_endscan(scan);
                }
-               heap_close(relation);
+               heap_close(relation, AccessShareLock);
        }
 
        ScanKeyEntryInitialize(&entry[0], 0,
@@ -643,8 +644,8 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
                                                   Anum_pg_amop_amopclaid,
                                                   F_OIDEQ, 0);
 
-       relation = heap_openr(AccessMethodOperatorRelationName);
-       operatorRelation = heap_openr(OperatorRelationName);
+       relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock);
+       operatorRelation = heap_openr(OperatorRelationName, AccessShareLock);
 
        for (attributeNumber = maxAttributeNumber; attributeNumber > 0;
                 attributeNumber--)
@@ -676,8 +677,8 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
                heap_endscan(scan);
        }
 
-       heap_close(operatorRelation);
-       heap_close(relation);
+       heap_close(operatorRelation, AccessShareLock);
+       heap_close(relation, AccessShareLock);
 }
 
 /* ----------------
index c97273f10f0cc0b528f3eb5a3dddfc217351f273..11f527fc3bad21b3b632e6a9efddc999a9ea5fa8 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.45 1999/07/17 20:16:43 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.46 1999/09/18 19:06:10 tgl Exp $
  *
  * NOTES
  *       This file contains only the public interface routines.
@@ -74,8 +74,6 @@ btbuild(Relation heap,
        TupleTableSlot *slot = (TupleTableSlot *) NULL;
 
 #endif
-       Oid                     hrelid,
-                               irelid;
        Node       *pred,
                           *oldPred;
        void       *spool = (void *) NULL;
@@ -301,17 +299,20 @@ btbuild(Relation heap,
        /*
         * Since we just counted the tuples in the heap, we update its stats
         * in pg_class to guarantee that the planner takes advantage of the
-        * index we just created. Finally, only update statistics during
+        * index we just created.  But, only update statistics during
         * normal index definitions, not for indices on system catalogs
         * created during bootstrap processing.  We must close the relations
-        * before updatings statistics to guarantee that the relcache entries
+        * before updating statistics to guarantee that the relcache entries
         * are flushed when we increment the command counter in UpdateStats().
+        * But we do not release any locks on the relations; those will be
+        * held until end of transaction.
         */
        if (IsNormalProcessingMode())
        {
-               hrelid = RelationGetRelid(heap);
-               irelid = RelationGetRelid(index);
-               heap_close(heap);
+               Oid             hrelid = RelationGetRelid(heap);
+               Oid             irelid = RelationGetRelid(index);
+
+               heap_close(heap, NoLock);
                index_close(index);
                UpdateStats(hrelid, nhtups, true);
                UpdateStats(irelid, nitups, false);
index 37da716df1d553b0415afd8cf911c90d14e07932..133bbdbc032c9a965d653cfbdd6c1279b65556a7 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.36 1999/07/17 20:16:45 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.37 1999/09/18 19:06:16 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,6 +19,7 @@
 #include "access/rtree.h"
 #include "catalog/index.h"
 #include "executor/executor.h"
+#include "miscadmin.h"
 #include "utils/geo_decls.h"
 
 
@@ -89,8 +90,6 @@ rtbuild(Relation heap,
        TupleTableSlot *slot;
 
 #endif
-       Oid                     hrelid,
-                               irelid;
        Node       *pred,
                           *oldPred;
        RTSTATE         rtState;
@@ -248,27 +247,30 @@ rtbuild(Relation heap,
 
        /*
         * Since we just counted the tuples in the heap, we update its stats
-        * in pg_relation to guarantee that the planner takes advantage of the
-        * index we just created.  UpdateStats() does a
-        * CommandCounterIncrement(), which flushes changed entries from the
-        * system relcache.  The act of constructing an index changes these
-        * heap and index tuples in the system catalogs, so they need to be
-        * flushed.  We close them to guarantee that they will be.
+        * in pg_class to guarantee that the planner takes advantage of the
+        * index we just created.  But, only update statistics during
+        * normal index definitions, not for indices on system catalogs
+        * created during bootstrap processing.  We must close the relations
+        * before updating statistics to guarantee that the relcache entries
+        * are flushed when we increment the command counter in UpdateStats().
+        * But we do not release any locks on the relations; those will be
+        * held until end of transaction.
         */
-
-       hrelid = RelationGetRelid(heap);
-       irelid = RelationGetRelid(index);
-       heap_close(heap);
-       index_close(index);
-
-       UpdateStats(hrelid, nh, true);
-       UpdateStats(irelid, ni, false);
-
-       if (oldPred != NULL)
+       if (IsNormalProcessingMode())
        {
-               if (ni == nh)
-                       pred = NULL;
-               UpdateIndexPredicate(irelid, oldPred, pred);
+               Oid             hrelid = RelationGetRelid(heap);
+               Oid             irelid = RelationGetRelid(index);
+
+               heap_close(heap, NoLock);
+               index_close(index);
+               UpdateStats(hrelid, nh, true);
+               UpdateStats(irelid, ni, false);
+               if (oldPred != NULL)
+               {
+                       if (ni == nh)
+                               pred = NULL;
+                       UpdateIndexPredicate(irelid, oldPred, pred);
+               }
        }
 
        /* be tidy */
index 1f44fb357ac3bc3052deeeabcbc933d288e33240..b26243b4257f8f4536766f07cdf556fc502fd2fe 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.31 1999/08/08 20:12:52 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.32 1999/09/18 19:06:21 tgl Exp $
  *
  * NOTES
  *       This file contains the high level access-method interface to the
@@ -405,8 +405,11 @@ InitializeTransactionLog(void)
         *       (these are created by amiint so they are guaranteed to exist)
         * ----------------
         */
-       logRelation = heap_openr(LogRelationName);
-       VariableRelation = heap_openr(VariableRelationName);
+       logRelation = heap_openr(LogRelationName, NoLock);
+       Assert(logRelation != NULL);
+       VariableRelation = heap_openr(VariableRelationName, NoLock);
+       Assert(VariableRelation != NULL);
+
        /* ----------------
         *       XXX TransactionLogUpdate requires that LogRelation
         *       is valid so we temporarily set it so we can initialize
index 135912e97de58ec2b4490557b2d4091d561ea339..989b506bb7ffac8c6927f3567b487b228740c535 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/transam/varsup.c,v 1.24 1999/07/15 23:03:03 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/transam/varsup.c,v 1.25 1999/09/18 19:06:21 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -441,7 +441,7 @@ GetNewObjectId(Oid *oid_return) /* place to return the new object id */
                 * ----------------
                 */
                if (!RelationIsValid(VariableRelation))
-                       VariableRelation = heap_openr(VariableRelationName);
+                       VariableRelation = heap_openr(VariableRelationName, NoLock);
 
                /* ----------------
                 *              get a new block of prefetched object ids.
index 8db37d0a081d1b379aa10b1d399d4833666821b4..18d9567ab898adeaf2dcf59dd193f0fed7e2c803 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.66 1999/07/19 02:27:04 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.67 1999/09/18 19:06:27 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -396,7 +396,8 @@ boot_openrel(char *relname)
        if (Typ == (struct typmap **) NULL)
        {
                StartPortalAllocMode(DefaultAllocMode, 0);
-               rel = heap_openr(TypeRelationName);
+               rel = heap_openr(TypeRelationName, NoLock);
+               Assert(rel);
                scan = heap_beginscan(rel, 0, SnapshotNow, 0, (ScanKey) NULL);
                i = 0;
                while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
@@ -416,7 +417,7 @@ boot_openrel(char *relname)
                                        sizeof((*app)->am_typ));
                }
                heap_endscan(scan);
-               heap_close(rel);
+               heap_close(rel, NoLock);
                EndPortalAllocMode();
        }
 
@@ -427,7 +428,7 @@ boot_openrel(char *relname)
                printf("Amopen: relation %s. attrsize %d\n", relname ? relname : "(null)",
                           (int) ATTRIBUTE_TUPLE_SIZE);
 
-       reldesc = heap_openr(relname);
+       reldesc = heap_openr(relname, NoLock);
        Assert(reldesc);
        numattr = reldesc->rd_rel->relnatts;
        for (i = 0; i < numattr; i++)
@@ -490,7 +491,7 @@ closerel(char *name)
        {
                if (!Quiet)
                        printf("Amclose: relation %s.\n", relname ? relname : "(null)");
-               heap_close(reldesc);
+               heap_close(reldesc, NoLock);
                reldesc = (Relation) NULL;
        }
 }
@@ -737,7 +738,7 @@ cleanup()
                proc_exit(1);
        }
        if (reldesc != (Relation) NULL)
-               heap_close(reldesc);
+               heap_close(reldesc, NoLock);
        CommitTransactionCommand();
        proc_exit(Warnings);
 }
@@ -775,7 +776,8 @@ gettype(char *type)
                }
                if (DebugMode)
                        printf("bootstrap.c: External Type: %s\n", type);
-               rel = heap_openr(TypeRelationName);
+               rel = heap_openr(TypeRelationName, NoLock);
+               Assert(rel);
                scan = heap_beginscan(rel, 0, SnapshotNow, 0, (ScanKey) NULL);
                i = 0;
                while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
@@ -795,7 +797,7 @@ gettype(char *type)
                                        sizeof((*app)->am_typ));
                }
                heap_endscan(scan);
-               heap_close(rel);
+               heap_close(rel, NoLock);
                return gettype(type);
        }
        elog(ERROR, "Error: unknown type '%s'.\n", type);
@@ -1106,11 +1108,16 @@ build_indices()
 
        for (; ILHead != (IndexList *) NULL; ILHead = ILHead->il_next)
        {
-               heap = heap_openr(ILHead->il_heap);
+               heap = heap_openr(ILHead->il_heap, NoLock);
+               Assert(heap);
                ind = index_openr(ILHead->il_ind);
+               Assert(ind);
                index_build(heap, ind, ILHead->il_natts, ILHead->il_attnos,
                                 ILHead->il_nparams, ILHead->il_params, ILHead->il_finfo,
                                        ILHead->il_predInfo);
+               /* In normal processing mode, index_build would close the heap
+                * and index, but in bootstrap mode it will not.
+                */
 
                /*
                 * All of the rest of this routine is needed only because in
@@ -1128,9 +1135,9 @@ build_indices()
                 *
                 * -mer
                 */
-               heap = heap_openr(ILHead->il_heap);
-
                if (!BootstrapAlreadySeen(RelationGetRelid(heap)))
                        UpdateStats(RelationGetRelid(heap), 0, true);
+
+               /* XXX Probably we ought to close the heap and index here? */
        }
 }
index 186ecd07f324cad17c100cf2c5cf7b781b8818d3..33a589ec88b1b81502b3bc3f09b0325382fc437e 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.27 1999/07/30 18:09:44 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.28 1999/09/18 19:06:33 tgl Exp $
  *
  * NOTES
  *       See acl.h.
@@ -105,19 +105,15 @@ ChangeAcl(char *relname,
         * We can't use the syscache here, since we need to do a heap_replace on
         * the tuple we find.
         */
-       relation = heap_openr(RelationRelationName);
-       if (!RelationIsValid(relation))
-               elog(ERROR, "ChangeAcl: could not open '%s'??",
-                        RelationRelationName);
+       relation = heap_openr(RelationRelationName, RowExclusiveLock);
        tuple = SearchSysCacheTuple(RELNAME,
                                                                PointerGetDatum(relname),
                                                                0, 0, 0);
        if (!HeapTupleIsValid(tuple))
        {
-               heap_close(relation);
+               heap_close(relation, RowExclusiveLock);
                elog(ERROR, "ChangeAcl: class \"%s\" not found",
                         relname);
-               return;
        }
 
        if (!heap_attisnull(tuple, Anum_pg_class_relacl))
@@ -164,7 +160,7 @@ ChangeAcl(char *relname,
        CatalogIndexInsert(idescs, Num_pg_class_indices, relation, tuple);
        CatalogCloseIndices(Num_pg_class_indices, idescs);
 
-       heap_close(relation);
+       heap_close(relation, RowExclusiveLock);
        if (free_old_acl)
                pfree(old_acl);
        pfree(new_acl);
@@ -213,13 +209,7 @@ in_group(AclId uid, AclId gid)
        AclId      *aidp;
        int32           found = 0;
 
-       relation = heap_openr(GroupRelationName);
-       if (!RelationIsValid(relation))
-       {
-               elog(NOTICE, "in_group: could not open \"%s\"??",
-                        GroupRelationName);
-               return 0;
-       }
+       relation = heap_openr(GroupRelationName, RowExclusiveLock);
        tuple = SearchSysCacheTuple(GROSYSID,
                                                                ObjectIdGetDatum(gid),
                                                                0, 0, 0);
@@ -242,7 +232,7 @@ in_group(AclId uid, AclId gid)
        }
        else
                elog(NOTICE, "in_group: group %d not found", gid);
-       heap_close(relation);
+       heap_close(relation, RowExclusiveLock);
        return found;
 }
 
@@ -413,6 +403,7 @@ pg_aclcheck(char *relname, char *usename, AclMode mode)
        }
 
 #ifndef ACLDEBUG
+       relation = heap_openr(RelationRelationName, RowExclusiveLock);
        tuple = SearchSysCacheTuple(RELNAME,
                                                                PointerGetDatum(relname),
                                                                0, 0, 0);
@@ -420,18 +411,15 @@ pg_aclcheck(char *relname, char *usename, AclMode mode)
        {
                elog(ERROR, "pg_aclcheck: class \"%s\" not found",
                         relname);
-               /* an elog(ERROR) kills us, so no need to return anything. */
        }
        if (!heap_attisnull(tuple, Anum_pg_class_relacl))
        {
-               relation = heap_openr(RelationRelationName);
                tmp = (Acl *) heap_getattr(tuple,
                                                                   Anum_pg_class_relacl,
                                                                   RelationGetDescr(relation),
                                                                   (bool *) NULL);
                acl = makeacl(ACL_NUM(tmp));
                memmove((char *) acl, (char *) tmp, ACL_SIZE(tmp));
-               heap_close(relation);
        }
        else
        {
@@ -442,42 +430,29 @@ pg_aclcheck(char *relname, char *usename, AclMode mode)
                 */
                int4            ownerId;
 
-               relation = heap_openr(RelationRelationName);
                ownerId = (int4) heap_getattr(tuple,
                                                                          Anum_pg_class_relowner,
                                                                          RelationGetDescr(relation),
                                                                          (bool *) NULL);
                acl = aclownerdefault(relname, (AclId) ownerId);
-               heap_close(relation);
        }
+       heap_close(relation, RowExclusiveLock);
 #else
-       {                                                       /* This is why the syscache is great... */
-               static ScanKeyData relkey[1] = {
-                       {0, Anum_pg_class_relname, F_NAMEEQ}
-               };
-
-               relation = heap_openr(RelationRelationName);
-               if (!RelationIsValid(relation))
-               {
-                       elog(NOTICE, "pg_checkacl: could not open \"%-.*s\"??",
-                                RelationRelationName);
-                       return ACLCHECK_NO_CLASS;
-               }
-               tuple = SearchSysCacheTuple(RELNAME,
-                                                                       PointerGetDatum(relname),
-                                                                       0, 0, 0);
-               if (HeapTupleIsValid(tuple) &&
-                       !heap_attisnull(tuple, Anum_pg_class_relacl))
-               {
-                       tmp = (Acl *) heap_getattr(tuple,
-                                                                          Anum_pg_class_relacl,
-                                                                          RelationGetDescr(relation),
-                                                                          (bool *) NULL);
-                       acl = makeacl(ACL_NUM(tmp));
-                       memmove((char *) acl, (char *) tmp, ACL_SIZE(tmp));
-               }
-               heap_close(relation);
+       relation = heap_openr(RelationRelationName, RowExclusiveLock);
+       tuple = SearchSysCacheTuple(RELNAME,
+                                                               PointerGetDatum(relname),
+                                                               0, 0, 0);
+       if (HeapTupleIsValid(tuple) &&
+               !heap_attisnull(tuple, Anum_pg_class_relacl))
+       {
+               tmp = (Acl *) heap_getattr(tuple,
+                                                                  Anum_pg_class_relacl,
+                                                                  RelationGetDescr(relation),
+                                                                  (bool *) NULL);
+               acl = makeacl(ACL_NUM(tmp));
+               memmove((char *) acl, (char *) tmp, ACL_SIZE(tmp));
        }
+       heap_close(relation, RowExclusiveLock);
 #endif
        result = aclcheck(relname, acl, id, (AclIdType) ACL_IDTYPE_UID, mode);
        if (acl)
index 561cb21a418d2479ad30cdd14eedae3cd5a1e0a9..644f03eba870a0406202ee4d6cd86c1274562f97 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.95 1999/09/05 17:43:47 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.96 1999/09/18 19:06:33 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -243,8 +243,6 @@ heap_create(char *relname,
 
        /* ----------------
         *      allocate a new relation descriptor.
-        *
-        *      XXX the length computation may be incorrect, handle elsewhere
         * ----------------
         */
        len = sizeof(RelationData);
@@ -474,7 +472,7 @@ RelnameFindRelid(char *relname)
                ScanKeyData key;
                HeapScanDesc pg_class_scan;
 
-               pg_class_desc = heap_openr(RelationRelationName);
+               pg_class_desc = heap_openr(RelationRelationName, AccessShareLock);
 
                /* ----------------
                 *      At bootstrap time, we have to do this the hard way.  Form the
@@ -511,7 +509,7 @@ RelnameFindRelid(char *relname)
 
                heap_endscan(pg_class_scan);
 
-               heap_close(pg_class_desc);
+               heap_close(pg_class_desc, AccessShareLock);
        }
        return relid;
 }
@@ -539,14 +537,12 @@ AddNewAttributeTuples(Oid new_rel_oid,
         *      open pg_attribute
         * ----------------
         */
-       rel = heap_openr(AttributeRelationName);
+       rel = heap_openr(AttributeRelationName, RowExclusiveLock);
 
        /* -----------------
         * Check if we have any indices defined on pg_attribute.
         * -----------------
         */
-       Assert(rel);
-       Assert(rel->rd_rel);
        hasindex = RelationGetForm(rel)->relhasindex;
        if (hasindex)
                CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
@@ -607,7 +603,7 @@ AddNewAttributeTuples(Oid new_rel_oid,
                dpp++;
        }
 
-       heap_close(rel);
+       heap_close(rel, RowExclusiveLock);
 
        /*
         * close pg_attribute indices
@@ -829,7 +825,7 @@ heap_create_with_catalog(char *relname,
         *      now update the information in pg_class.
         * ----------------
         */
-       pg_class_desc = heap_openr(RelationRelationName);
+       pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock);
 
        AddNewRelationTuple(pg_class_desc,
                                                new_rel_desc,
@@ -853,8 +849,8 @@ heap_create_with_catalog(char *relname,
         *      SOMEDAY: fill the STATISTIC relation properly.
         * ----------------
         */
-       heap_close(new_rel_desc);
-       heap_close(pg_class_desc);
+       heap_close(new_rel_desc, NoLock); /* do not unlock till end of xact */
+       heap_close(pg_class_desc, RowExclusiveLock);
 
        return new_rel_oid;
 }
@@ -913,7 +909,7 @@ RelationRemoveInheritance(Relation relation)
         *      open pg_inherits
         * ----------------
         */
-       catalogRelation = heap_openr(InheritsRelationName);
+       catalogRelation = heap_openr(InheritsRelationName, RowExclusiveLock);
 
        /* ----------------
         *      form a scan key for the subclasses of this class
@@ -937,13 +933,15 @@ RelationRemoveInheritance(Relation relation)
        tuple = heap_getnext(scan, 0);
        if (HeapTupleIsValid(tuple))
        {
+               Oid             subclass = ((Form_pg_inherits) GETSTRUCT(tuple))->inhrel;
+
                heap_endscan(scan);
-               heap_close(catalogRelation);
+               heap_close(catalogRelation, RowExclusiveLock);
 
                elog(ERROR, "Relation '%u' inherits '%s'",
-                        ((Form_pg_inherits) GETSTRUCT(tuple))->inhrel,
-                        RelationGetRelationName(relation));
+                        subclass, RelationGetRelationName(relation));
        }
+       heap_endscan(scan);
 
        /* ----------------
         *      If we get here, it means the relation has no subclasses
@@ -965,13 +963,14 @@ RelationRemoveInheritance(Relation relation)
        }
 
        heap_endscan(scan);
-       heap_close(catalogRelation);
+       heap_close(catalogRelation, RowExclusiveLock);
 
        /* ----------------
         *      now remove dead IPL tuples
         * ----------------
         */
-       catalogRelation = heap_openr(InheritancePrecidenceListRelationName);
+       catalogRelation = heap_openr(InheritancePrecidenceListRelationName,
+                                                                RowExclusiveLock);
 
        entry.sk_attno = Anum_pg_ipl_iplrel;
 
@@ -985,7 +984,7 @@ RelationRemoveInheritance(Relation relation)
                heap_delete(catalogRelation, &tuple->t_self, NULL);
 
        heap_endscan(scan);
-       heap_close(catalogRelation);
+       heap_close(catalogRelation, RowExclusiveLock);
 }
 
 /* --------------------------------
@@ -1001,7 +1000,7 @@ RelationRemoveIndexes(Relation relation)
        HeapScanDesc scan;
        ScanKeyData entry;
 
-       indexRelation = heap_openr(IndexRelationName);
+       indexRelation = heap_openr(IndexRelationName, RowExclusiveLock);
 
        ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_index_indrelid,
                                                   F_OIDEQ,
@@ -1017,7 +1016,7 @@ RelationRemoveIndexes(Relation relation)
                index_destroy(((Form_pg_index) GETSTRUCT(tuple))->indexrelid);
 
        heap_endscan(scan);
-       heap_close(indexRelation);
+       heap_close(indexRelation, RowExclusiveLock);
 }
 
 /* --------------------------------
@@ -1035,14 +1034,14 @@ DeleteRelationTuple(Relation rel)
         *      open pg_class
         * ----------------
         */
-       pg_class_desc = heap_openr(RelationRelationName);
+       pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock);
 
        tup = SearchSysCacheTupleCopy(RELOID,
                                           ObjectIdGetDatum(rel->rd_att->attrs[0]->attrelid),
                                                                  0, 0, 0);
        if (!HeapTupleIsValid(tup))
        {
-               heap_close(pg_class_desc);
+               heap_close(pg_class_desc, RowExclusiveLock);
                elog(ERROR, "Relation '%s' does not exist",
                         &rel->rd_rel->relname);
        }
@@ -1054,7 +1053,7 @@ DeleteRelationTuple(Relation rel)
        heap_delete(pg_class_desc, &tup->t_self, NULL);
        pfree(tup);
 
-       heap_close(pg_class_desc);
+       heap_close(pg_class_desc, RowExclusiveLock);
 }
 
 /* --------------------------------
@@ -1073,13 +1072,7 @@ DeleteAttributeTuples(Relation rel)
         *      open pg_attribute
         * ----------------
         */
-       pg_attribute_desc = heap_openr(AttributeRelationName);
-
-       /* -----------------
-        * Get a write lock _before_ getting the read lock in the scan
-        * ----------------
-        */
-       LockRelation(pg_attribute_desc, AccessExclusiveLock);
+       pg_attribute_desc = heap_openr(AttributeRelationName, RowExclusiveLock);
 
        for (attnum = FirstLowInvalidHeapAttributeNumber + 1;
                 attnum <= rel->rd_att->natts;
@@ -1095,12 +1088,7 @@ DeleteAttributeTuples(Relation rel)
                }
        }
 
-       /* ----------------
-        * Release the write lock
-        * ----------------
-        */
-       UnlockRelation(pg_attribute_desc, AccessExclusiveLock);
-       heap_close(pg_attribute_desc);
+       heap_close(pg_attribute_desc, RowExclusiveLock);
 }
 
 /* --------------------------------
@@ -1129,7 +1117,7 @@ DeleteTypeTuple(Relation rel)
         *      open pg_type
         * ----------------
         */
-       pg_type_desc = heap_openr(TypeRelationName);
+       pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
 
        /* ----------------
         *      create a scan key to locate the type tuple corresponding
@@ -1157,7 +1145,7 @@ DeleteTypeTuple(Relation rel)
        if (!HeapTupleIsValid(tup))
        {
                heap_endscan(pg_type_scan);
-               heap_close(pg_type_desc);
+               heap_close(pg_type_desc, RowExclusiveLock);
                elog(ERROR, "DeleteTypeTuple: %s type nonexistent",
                         &rel->rd_rel->relname);
        }
@@ -1171,7 +1159,7 @@ DeleteTypeTuple(Relation rel)
         */
        typoid = tup->t_data->t_oid;
 
-       pg_attribute_desc = heap_openr(AttributeRelationName);
+       pg_attribute_desc = heap_openr(AttributeRelationName, RowExclusiveLock);
 
        ScanKeyEntryInitialize(&attkey,
                                                   0,
@@ -1197,16 +1185,16 @@ DeleteTypeTuple(Relation rel)
        {
                Oid                     relid = ((Form_pg_attribute) GETSTRUCT(atttup))->attrelid;
 
-               heap_endscan(pg_type_scan);
-               heap_close(pg_type_desc);
                heap_endscan(pg_attribute_scan);
-               heap_close(pg_attribute_desc);
+               heap_close(pg_attribute_desc, RowExclusiveLock);
+               heap_endscan(pg_type_scan);
+               heap_close(pg_type_desc, RowExclusiveLock);
 
                elog(ERROR, "DeleteTypeTuple: att of type %s exists in relation %u",
                         &rel->rd_rel->relname, relid);
        }
        heap_endscan(pg_attribute_scan);
-       heap_close(pg_attribute_desc);
+       heap_close(pg_attribute_desc, RowExclusiveLock);
 
        /* ----------------
         *      Ok, it's safe so we delete the relation tuple
@@ -1217,7 +1205,7 @@ DeleteTypeTuple(Relation rel)
        heap_delete(pg_type_desc, &tup->t_self, NULL);
 
        heap_endscan(pg_type_scan);
-       heap_close(pg_type_desc);
+       heap_close(pg_type_desc, RowExclusiveLock);
 }
 
 /* --------------------------------
@@ -1233,15 +1221,10 @@ heap_destroy_with_catalog(char *relname)
        bool            istemp = (get_temp_rel_by_name(relname) != NULL);
 
        /* ----------------
-        *      first open the relation.  if the relation doesn't exist,
-        *      heap_openr() returns NULL.
+        *      Open and lock the relation.
         * ----------------
         */
-       rel = heap_openr(relname);
-       if (rel == NULL)
-               elog(ERROR, "Relation '%s' does not exist", relname);
-
-       LockRelation(rel, AccessExclusiveLock);
+       rel = heap_openr(relname, AccessExclusiveLock);
        rid = rel->rd_id;
 
        /* ----------------
@@ -1249,8 +1232,8 @@ heap_destroy_with_catalog(char *relname)
         * ----------------
         */
        /* allow temp of pg_class? Guess so. */
-       if (!istemp &&
-               !allowSystemTableMods && IsSystemRelationName(RelationGetRelationName(rel)->data))
+       if (!istemp && !allowSystemTableMods &&
+               IsSystemRelationName(RelationGetRelationName(rel)->data))
                elog(ERROR, "System relation '%s' cannot be destroyed",
                         &rel->rd_rel->relname);
 
@@ -1330,9 +1313,12 @@ heap_destroy_with_catalog(char *relname)
 
        rel->rd_nonameunlinked = TRUE;
 
-       UnlockRelation(rel, AccessExclusiveLock);
-
-       heap_close(rel);
+       /*
+        * Close relcache entry, but *keep* AccessExclusiveLock on the
+        * relation until transaction commit.  This ensures no one else
+        * will try to do something with the doomed relation.
+        */
+       heap_close(rel, NoLock);
 
        /* ----------------
         *      flush the relation from the relcache
@@ -1354,7 +1340,7 @@ heap_destroy(Relation rel)
        if (!(rel->rd_isnoname) || !(rel->rd_nonameunlinked))
                smgrunlink(DEFAULT_SMGR, rel);
        rel->rd_nonameunlinked = TRUE;
-       heap_close(rel);
+       heap_close(rel, NoLock);
        RemoveFromNoNameRelList(rel);
 }
 
@@ -1542,13 +1528,13 @@ start:
        values[Anum_pg_attrdef_adnum - 1] = attrdef->adnum;
        values[Anum_pg_attrdef_adbin - 1] = PointerGetDatum(textin(attrdef->adbin));
        values[Anum_pg_attrdef_adsrc - 1] = PointerGetDatum(textin(attrdef->adsrc));
-       adrel = heap_openr(AttrDefaultRelationName);
+       adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
        tuple = heap_formtuple(adrel->rd_att, values, nulls);
        CatalogOpenIndices(Num_pg_attrdef_indices, Name_pg_attrdef_indices, idescs);
        heap_insert(adrel, tuple);
        CatalogIndexInsert(idescs, Num_pg_attrdef_indices, adrel, tuple);
        CatalogCloseIndices(Num_pg_attrdef_indices, idescs);
-       heap_close(adrel);
+       heap_close(adrel, RowExclusiveLock);
 
        pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
        pfree(DatumGetPointer(values[Anum_pg_attrdef_adsrc - 1]));
@@ -1605,20 +1591,18 @@ StoreRelCheck(Relation rel, ConstrCheck *check)
        values[Anum_pg_relcheck_rcname - 1] = PointerGetDatum(namein(check->ccname));
        values[Anum_pg_relcheck_rcbin - 1] = PointerGetDatum(textin(check->ccbin));
        values[Anum_pg_relcheck_rcsrc - 1] = PointerGetDatum(textin(check->ccsrc));
-       rcrel = heap_openr(RelCheckRelationName);
+       rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock);
        tuple = heap_formtuple(rcrel->rd_att, values, nulls);
        CatalogOpenIndices(Num_pg_relcheck_indices, Name_pg_relcheck_indices, idescs);
        heap_insert(rcrel, tuple);
        CatalogIndexInsert(idescs, Num_pg_relcheck_indices, rcrel, tuple);
        CatalogCloseIndices(Num_pg_relcheck_indices, idescs);
-       heap_close(rcrel);
+       heap_close(rcrel, RowExclusiveLock);
 
        pfree(DatumGetPointer(values[Anum_pg_relcheck_rcname - 1]));
        pfree(DatumGetPointer(values[Anum_pg_relcheck_rcbin - 1]));
        pfree(DatumGetPointer(values[Anum_pg_relcheck_rcsrc - 1]));
        pfree(tuple);
-
-       return;
 }
 
 static void
@@ -1653,23 +1637,18 @@ RemoveAttrDefault(Relation rel)
        ScanKeyData key;
        HeapTuple       tup;
 
-       adrel = heap_openr(AttrDefaultRelationName);
+       adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
 
        ScanKeyEntryInitialize(&key, 0, Anum_pg_attrdef_adrelid,
                                                   F_OIDEQ, rel->rd_id);
 
-       LockRelation(adrel, AccessExclusiveLock);
-
        adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key);
 
        while (HeapTupleIsValid(tup = heap_getnext(adscan, 0)))
                heap_delete(adrel, &tup->t_self, NULL);
 
        heap_endscan(adscan);
-
-       UnlockRelation(adrel, AccessExclusiveLock);
-       heap_close(adrel);
-
+       heap_close(adrel, RowExclusiveLock);
 }
 
 static void
@@ -1680,23 +1659,18 @@ RemoveRelCheck(Relation rel)
        ScanKeyData key;
        HeapTuple       tup;
 
-       rcrel = heap_openr(RelCheckRelationName);
+       rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock);
 
        ScanKeyEntryInitialize(&key, 0, Anum_pg_relcheck_rcrelid,
                                                   F_OIDEQ, rel->rd_id);
 
-       LockRelation(rcrel, AccessExclusiveLock);
-
        rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key);
 
        while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0)))
                heap_delete(rcrel, &tup->t_self, NULL);
 
        heap_endscan(rcscan);
-
-       UnlockRelation(rcrel, AccessExclusiveLock);
-       heap_close(rcrel);
-
+       heap_close(rcrel, RowExclusiveLock);
 }
 
 static void
@@ -1712,6 +1686,4 @@ RemoveConstraints(Relation rel)
 
        if (constr->num_check > 0)
                RemoveRelCheck(rel);
-
-       return;
 }
index c90c27fd5de55c64cfb922714d07e37ceb865e25..912996fb1fc7f8a92882ef64bd91505421a88712 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.89 1999/09/05 17:43:47 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.90 1999/09/18 19:06:33 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -378,7 +378,7 @@ AccessMethodObjectIdGetForm(Oid accessMethodObjectId)
         *      fetch the desired access method tuple
         * ----------------
         */
-       pg_am_desc = heap_openr(AccessMethodRelationName);
+       pg_am_desc = heap_openr(AccessMethodRelationName, AccessShareLock);
        pg_am_scan = heap_beginscan(pg_am_desc, 0, SnapshotNow, 1, &key);
 
        pg_am_tuple = heap_getnext(pg_am_scan, 0);
@@ -390,7 +390,7 @@ AccessMethodObjectIdGetForm(Oid accessMethodObjectId)
        if (!HeapTupleIsValid(pg_am_tuple))
        {
                heap_endscan(pg_am_scan);
-               heap_close(pg_am_desc);
+               heap_close(pg_am_desc, AccessShareLock);
                return NULL;
        }
 
@@ -402,7 +402,7 @@ AccessMethodObjectIdGetForm(Oid accessMethodObjectId)
        memcpy(aform, GETSTRUCT(pg_am_tuple), sizeof *aform);
 
        heap_endscan(pg_am_scan);
-       heap_close(pg_am_desc);
+       heap_close(pg_am_desc, AccessShareLock);
 
        return aform;
 }
@@ -456,7 +456,7 @@ UpdateRelationRelation(Relation indexRelation, char *temp_relname)
        Oid                     tupleOid;
        Relation        idescs[Num_pg_class_indices];
 
-       pg_class = heap_openr(RelationRelationName);
+       pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
 
        /* XXX Natts_pg_class_fixed is a hack - see pg_class.h */
        tuple = heap_addheader(Natts_pg_class_fixed,
@@ -491,7 +491,7 @@ UpdateRelationRelation(Relation indexRelation, char *temp_relname)
 
        tupleOid = tuple->t_data->t_oid;
        pfree(tuple);
-       heap_close(pg_class);
+       heap_close(pg_class, RowExclusiveLock);
 
        return tupleOid;
 }
@@ -542,7 +542,7 @@ AppendAttributeTuples(Relation indexRelation, int numatts)
         *      XXX ADD INDEXING
         * ----------------
         */
-       pg_attribute = heap_openr(AttributeRelationName);
+       pg_attribute = heap_openr(AttributeRelationName, RowExclusiveLock);
 
        /* ----------------
         *      initialize *null, *replace and *value
@@ -628,7 +628,7 @@ AppendAttributeTuples(Relation indexRelation, int numatts)
 
        if (cur_tuple)
                pfree(cur_tuple);
-       heap_close(pg_attribute);
+       heap_close(pg_attribute, RowExclusiveLock);
        if (hasind)
                CatalogCloseIndices(Num_pg_attr_indices, idescs);
 
@@ -734,7 +734,7 @@ UpdateIndexRelation(Oid indexoid,
         *      open the system catalog index relation
         * ----------------
         */
-       pg_index = heap_openr(IndexRelationName);
+       pg_index = heap_openr(IndexRelationName, RowExclusiveLock);
 
        /* ----------------
         *      form a tuple to insert into pg_index
@@ -755,7 +755,7 @@ UpdateIndexRelation(Oid indexoid,
         *      close the relation and free the tuple
         * ----------------
         */
-       heap_close(pg_index);
+       heap_close(pg_index, RowExclusiveLock);
        pfree(predText);
        pfree(indexForm);
        pfree(tuple);
@@ -810,7 +810,7 @@ UpdateIndexPredicate(Oid indexoid, Node *oldPred, Node *predicate)
                predText = (text *) fmgr(F_TEXTIN, "");
 
        /* open the index system catalog relation */
-       pg_index = heap_openr(IndexRelationName);
+       pg_index = heap_openr(IndexRelationName, RowExclusiveLock);
 
        tuple = SearchSysCacheTuple(INDEXRELID,
                                                                ObjectIdGetDatum(indexoid),
@@ -832,7 +832,7 @@ UpdateIndexPredicate(Oid indexoid, Node *oldPred, Node *predicate)
        heap_replace(pg_index, &newtup->t_self, newtup, NULL);
 
        pfree(newtup);
-       heap_close(pg_index);
+       heap_close(pg_index, RowExclusiveLock);
        pfree(predText);
 }
 
@@ -956,12 +956,10 @@ index_create(char *heapRelationName,
         */
        heapoid = GetHeapRelationOid(heapRelationName, indexRelationName, istemp);
 
-       heapRelation = heap_open(heapoid);
-
        /*
-        * Only SELECT ... FOR UPDATE are allowed
+        * Only SELECT ... FOR UPDATE are allowed while doing this
         */
-       LockRelation(heapRelation, ShareLock);
+       heapRelation = heap_open(heapoid, ShareLock);
 
        /* ----------------
         *        construct new tuple descriptor
@@ -1070,16 +1068,20 @@ index_create(char *heapRelationName,
         * the index yet.  We'll be creating more indices and classes later,
         * so we delay filling them in until just before we're done with
         * bootstrapping.  Otherwise, we call the routine that constructs the
-        * index.  The heap and index relations are closed by index_build().
+        * index.
+        *
+        * In normal processing mode, the heap and index relations are closed
+        * by index_build() --- but we continue to hold the ShareLock on the
+        * heap that we acquired above, until end of transaction.
         */
        if (IsBootstrapProcessingMode())
        {
                index_register(heapRelationName, indexRelationName, numatts, attNums,
                                           parameterCount, parameter, funcInfo, predInfo);
+               /* XXX shouldn't we close the heap and index rels here? */
        }
        else
        {
-               heapRelation = heap_openr(heapRelationName);
                index_build(heapRelation, indexRelation, numatts, attNums,
                                        parameterCount, parameter, funcInfo, predInfo);
        }
@@ -1103,9 +1105,13 @@ index_destroy(Oid indexId)
 
        Assert(OidIsValid(indexId));
 
-       /* Open now to obtain lock by referencing table?  bjm */
        userindexRelation = index_open(indexId);
 
+       /*
+        * Get exclusive lock to ensure no one else is scanning this index.
+        */
+       LockRelation(userindexRelation, AccessExclusiveLock);
+
        /* ----------------
         *      We do not allow DROP INDEX within a transaction block, because
         *      if the transaction is later rolled back there would be no way to
@@ -1121,7 +1127,7 @@ index_destroy(Oid indexId)
         * fix RELATION relation
         * ----------------
         */
-       relationRelation = heap_openr(RelationRelationName);
+       relationRelation = heap_openr(RelationRelationName, RowExclusiveLock);
 
        tuple = SearchSysCacheTupleCopy(RELOID,
                                                                        ObjectIdGetDatum(indexId),
@@ -1131,13 +1137,13 @@ index_destroy(Oid indexId)
 
        heap_delete(relationRelation, &tuple->t_self, NULL);
        pfree(tuple);
-       heap_close(relationRelation);
+       heap_close(relationRelation, RowExclusiveLock);
 
        /* ----------------
         * fix ATTRIBUTE relation
         * ----------------
         */
-       attributeRelation = heap_openr(AttributeRelationName);
+       attributeRelation = heap_openr(AttributeRelationName, RowExclusiveLock);
 
        attnum = 1;                                     /* indexes start at 1 */
 
@@ -1150,7 +1156,7 @@ index_destroy(Oid indexId)
                pfree(tuple);
                attnum++;
        }
-       heap_close(attributeRelation);
+       heap_close(attributeRelation, RowExclusiveLock);
 
        /* does something only if it is a temp index */
        remove_temp_relation(indexId);
@@ -1159,16 +1165,16 @@ index_destroy(Oid indexId)
         * fix INDEX relation
         * ----------------
         */
+       indexRelation = heap_openr(IndexRelationName, RowExclusiveLock);
+
        tuple = SearchSysCacheTupleCopy(INDEXRELID,
                                                                        ObjectIdGetDatum(indexId),
                                                                        0, 0, 0);
        Assert(HeapTupleIsValid(tuple));
 
-       indexRelation = heap_openr(IndexRelationName);
-
        heap_delete(indexRelation, &tuple->t_self, NULL);
        pfree(tuple);
-       heap_close(indexRelation);
+       heap_close(indexRelation, RowExclusiveLock);
 
        /*
         * flush cache and physically remove the file
@@ -1179,7 +1185,8 @@ index_destroy(Oid indexId)
                elog(ERROR, "index_destroy: unlink: %m");
 
        index_close(userindexRelation);
-       RelationForgetRelation(RelationGetRelid(userindexRelation));
+
+       RelationForgetRelation(indexId);
 }
 
 /* ----------------------------------------------------------------
@@ -1264,16 +1271,21 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
         * ----------------
         */
 
+       /*
+        * Can't use heap_open here since we don't know if it's an index...
+        */
        whichRel = RelationIdGetRelation(relid);
 
        if (!RelationIsValid(whichRel))
                elog(ERROR, "UpdateStats: cannot open relation id %u", relid);
 
+       LockRelation(whichRel, ShareLock);
+
        /* ----------------
         * Find the RELATION relation tuple for the given relation.
         * ----------------
         */
-       pg_class = heap_openr(RelationRelationName);
+       pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
        if (!RelationIsValid(pg_class))
                elog(ERROR, "UpdateStats: could not open RELATION relation");
 
@@ -1300,7 +1312,7 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
        {
                if (IsBootstrapProcessingMode())
                        heap_endscan(pg_class_scan);
-               heap_close(pg_class);
+               heap_close(pg_class, RowExclusiveLock);
                elog(ERROR, "UpdateStats: cannot scan RELATION relation");
        }
 
@@ -1391,8 +1403,9 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
        else
                heap_endscan(pg_class_scan);
 
-       heap_close(pg_class);
-       heap_close(whichRel);
+       heap_close(pg_class, RowExclusiveLock);
+       /* Cheating a little bit since we didn't open it with heap_open... */
+       heap_close(whichRel, ShareLock);
 }
 
 
@@ -1600,20 +1613,31 @@ DefaultBuild(Relation heapRelation,
        pfree(datum);
 
        /*
-        * Okay, now update the reltuples and relpages statistics for both the
-        * heap relation and the index.  These statistics are used by the
-        * planner to choose a scan type.  They are maintained generally by
-        * the vacuum daemon, but we update them here to make the index useful
-        * as soon as possible.
-        */
-       UpdateStats(RelationGetRelid(heapRelation), reltuples, true);
-       UpdateStats(RelationGetRelid(indexRelation), indtuples, false);
-       if (oldPred != NULL)
+        * Since we just counted the tuples in the heap, we update its stats
+        * in pg_class to guarantee that the planner takes advantage of the
+        * index we just created.  But, only update statistics during
+        * normal index definitions, not for indices on system catalogs
+        * created during bootstrap processing.  We must close the relations
+        * before updating statistics to guarantee that the relcache entries
+        * are flushed when we increment the command counter in UpdateStats().
+        * But we do not release any locks on the relations; those will be
+        * held until end of transaction.
+        */
+       if (IsNormalProcessingMode())
        {
-               if (indtuples == reltuples)
-                       predicate = NULL;
-               UpdateIndexPredicate(RelationGetRelid(indexRelation),
-                                                        oldPred, predicate);
+               Oid             hrelid = RelationGetRelid(heapRelation);
+               Oid             irelid = RelationGetRelid(indexRelation);
+
+               heap_close(heapRelation, NoLock);
+               index_close(indexRelation);
+               UpdateStats(hrelid, reltuples, true);
+               UpdateStats(irelid, indtuples, false);
+               if (oldPred != NULL)
+               {
+                       if (indtuples == reltuples)
+                               predicate = NULL;
+                       UpdateIndexPredicate(irelid, oldPred, predicate);
+               }
        }
 }
 
@@ -1715,7 +1739,7 @@ IndexIsUniqueNoCache(Oid indexId)
        Form_pg_index index;
        bool            isunique;
 
-       pg_index = heap_openr(IndexRelationName);
+       pg_index = heap_openr(IndexRelationName, AccessShareLock);
 
        ScanKeyEntryInitialize(&skey[0], (bits16) 0x0,
                                                   Anum_pg_index_indexrelid,
@@ -1734,6 +1758,6 @@ IndexIsUniqueNoCache(Oid indexId)
        isunique = index->indisunique;
 
        heap_endscan(scandesc);
-       heap_close(pg_index);
+       heap_close(pg_index, AccessShareLock);
        return isunique;
 }
index 9007258f2e81792cc2f2ed1dc1fdf3d6fc1c8404..75799e55570fddc561657cf3d7a7c28aec1556be 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.44 1999/09/04 22:00:29 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.45 1999/09/18 19:06:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -193,9 +193,9 @@ CatalogHasIndex(char *catName, Oid catId)
                return false;
        }
 
-       pg_class = heap_openr(RelationRelationName);
+       pg_class = heap_openr(RelationRelationName, AccessShareLock);
        htup = ClassOidIndexScan(pg_class, catId);
-       heap_close(pg_class);
+       heap_close(pg_class, AccessShareLock);
 
        if (!HeapTupleIsValid(htup))
        {
index c8f02287cb80741545f1b69621af1abc01e3b823..0f2b98da906c2ec0c5f24b185613b23b5e90e28e 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.24 1999/07/17 20:16:49 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.25 1999/09/18 19:06:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -234,10 +234,7 @@ AggregateCreate(char *aggName,
        else
                nulls[Anum_pg_aggregate_agginitval2 - 1] = 'n';
 
-       if (!RelationIsValid(aggdesc = heap_openr(AggregateRelationName)))
-               elog(ERROR, "AggregateCreate: could not open '%s'",
-                        AggregateRelationName);
-
+       aggdesc = heap_openr(AggregateRelationName, RowExclusiveLock);
        tupDesc = aggdesc->rd_att;
        if (!HeapTupleIsValid(tup = heap_formtuple(tupDesc,
                                                                                           values,
@@ -245,8 +242,7 @@ AggregateCreate(char *aggName,
                elog(ERROR, "AggregateCreate: heap_formtuple failed");
        if (!OidIsValid(heap_insert(aggdesc, tup)))
                elog(ERROR, "AggregateCreate: heap_insert failed");
-       heap_close(aggdesc);
-
+       heap_close(aggdesc, RowExclusiveLock);
 }
 
 char *
@@ -264,6 +260,14 @@ AggNameGetInitVal(char *aggName, Oid basetype, int xfuncno, bool *isNull)
        Assert(PointerIsValid(isNull));
        Assert(xfuncno == 1 || xfuncno == 2);
 
+       /*
+        * since we will have to use fastgetattr (in case one or both init vals
+        * are NULL), we will need to open the relation.  Do that first to
+        * ensure we don't get a stale tuple from the cache.
+        */
+
+       aggRel = heap_openr(AggregateRelationName, AccessShareLock);
+
        tup = SearchSysCacheTuple(AGGNAME,
                                                          PointerGetDatum(aggName),
                                                          ObjectIdGetDatum(basetype),
@@ -277,21 +281,12 @@ AggNameGetInitVal(char *aggName, Oid basetype, int xfuncno, bool *isNull)
                initValAttno = Anum_pg_aggregate_agginitval1;
        }
        else
-               /* can only be 1 or 2 */
        {
+               /* can only be 1 or 2 */
                transtype = ((Form_pg_aggregate) GETSTRUCT(tup))->aggtranstype2;
                initValAttno = Anum_pg_aggregate_agginitval2;
        }
 
-       aggRel = heap_openr(AggregateRelationName);
-       if (!RelationIsValid(aggRel))
-               elog(ERROR, "AggNameGetInitVal: could not open \"%-.*s\"",
-                        AggregateRelationName);
-
-       /*
-        * must use fastgetattr in case one or other of the init values is
-        * NULL
-        */
        textInitVal = (text *) fastgetattr(tup, initValAttno,
                                                                           RelationGetDescr(aggRel),
                                                                           isNull);
@@ -299,11 +294,12 @@ AggNameGetInitVal(char *aggName, Oid basetype, int xfuncno, bool *isNull)
                *isNull = true;
        if (*isNull)
        {
-               heap_close(aggRel);
+               heap_close(aggRel, AccessShareLock);
                return (char *) NULL;
        }
        strInitVal = textout(textInitVal);
-       heap_close(aggRel);
+
+       heap_close(aggRel, AccessShareLock);
 
        tup = SearchSysCacheTuple(TYPOID,
                                                          ObjectIdGetDatum(transtype),
index 8cab520f520fa2013734b5840969063c5be752f7..53b250fe3fabb7c26769a0f935140d274d47cccd 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.41 1999/07/17 20:16:49 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.42 1999/09/18 19:06:33 tgl Exp $
  *
  * NOTES
  *       these routines moved here from commands/define.c and somewhat cleaned up.
@@ -199,7 +199,7 @@ OperatorGet(char *operatorName,
         *      open the pg_operator relation
         * ----------------
         */
-       pg_operator_desc = heap_openr(OperatorRelationName);
+       pg_operator_desc = heap_openr(OperatorRelationName, AccessShareLock);
 
        /* ----------------
         *      get the oid for the operator with the appropriate name
@@ -216,7 +216,7 @@ OperatorGet(char *operatorName,
         *      close the relation and return the operator oid.
         * ----------------
         */
-       heap_close(pg_operator_desc);
+       heap_close(pg_operator_desc, AccessShareLock);
 
        return operatorObjectId;
 }
@@ -341,7 +341,7 @@ OperatorShellMake(char *operatorName,
         *      open pg_operator
         * ----------------
         */
-       pg_operator_desc = heap_openr(OperatorRelationName);
+       pg_operator_desc = heap_openr(OperatorRelationName, RowExclusiveLock);
 
        /* ----------------
         *      add a "shell" operator tuple to the operator relation
@@ -356,7 +356,7 @@ OperatorShellMake(char *operatorName,
         *      close the operator relation and return the oid.
         * ----------------
         */
-       heap_close(pg_operator_desc);
+       heap_close(pg_operator_desc, RowExclusiveLock);
 
        return operatorObjectId;
 }
@@ -754,10 +754,11 @@ OperatorDef(char *operatorName,
 
        /* last three fields were filled in above */
 
+       pg_operator_desc = heap_openr(OperatorRelationName, RowExclusiveLock);
+
        /*
         * If we are adding to an operator shell, get its t_self
         */
-       pg_operator_desc = heap_openr(OperatorRelationName);
 
        if (operatorObjectId)
        {
@@ -798,7 +799,7 @@ OperatorDef(char *operatorName,
                operatorObjectId = tup->t_data->t_oid;
        }
 
-       heap_close(pg_operator_desc);
+       heap_close(pg_operator_desc, RowExclusiveLock);
 
        /*
         * If a commutator and/or negator link is provided, update the other
@@ -853,7 +854,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
                nulls[i] = ' ';
        }
 
-       pg_operator_desc = heap_openr(OperatorRelationName);
+       pg_operator_desc = heap_openr(OperatorRelationName, RowExclusiveLock);
 
        /* check and update the commutator, if necessary */
        opKey[0].sk_argument = ObjectIdGetDatum(commId);
@@ -908,7 +909,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
                }
                heap_endscan(pg_operator_scan);
 
-               heap_close(pg_operator_desc);
+               heap_close(pg_operator_desc, RowExclusiveLock);
 
                return;
        }
@@ -964,7 +965,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
 
        heap_endscan(pg_operator_scan);
 
-       heap_close(pg_operator_desc);
+       heap_close(pg_operator_desc, RowExclusiveLock);
 }
 
 
index f0a10cf8f89092871099f2e220c33912b98fd413..b71f36e6618858f4624982564bee0075dfe063d2 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.33 1999/07/17 20:16:49 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.34 1999/09/18 19:06:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -277,7 +277,7 @@ ProcedureCreate(char *procedureName,
        values[i++] = (Datum) fmgr(F_TEXTIN, prosrc);           /* prosrc */
        values[i++] = (Datum) fmgr(F_TEXTIN, probin);           /* probin */
 
-       rel = heap_openr(ProcedureRelationName);
+       rel = heap_openr(ProcedureRelationName, RowExclusiveLock);
 
        tupDesc = rel->rd_att;
        tup = heap_formtuple(tupDesc,
@@ -294,6 +294,6 @@ ProcedureCreate(char *procedureName,
                CatalogIndexInsert(idescs, Num_pg_proc_indices, rel, tup);
                CatalogCloseIndices(Num_pg_proc_indices, idescs);
        }
-       heap_close(rel);
+       heap_close(rel, RowExclusiveLock);
        return tup->t_data->t_oid;
 }
index a219767858c1c225478a288aeedd461da30bb348..91c7cd995ba47254a3659d2204144e101390db8c 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.40 1999/07/17 20:16:50 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.41 1999/09/18 19:06:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -119,7 +119,7 @@ TypeGet(char *typeName,                     /* name of type to be fetched */
         *      open the pg_type relation
         * ----------------
         */
-       pg_type_desc = heap_openr(TypeRelationName);
+       pg_type_desc = heap_openr(TypeRelationName, AccessShareLock);
 
        /* ----------------
         *      scan the type relation for the information we want
@@ -133,7 +133,7 @@ TypeGet(char *typeName,                     /* name of type to be fetched */
         *      close the type relation and return the type oid.
         * ----------------
         */
-       heap_close(pg_type_desc);
+       heap_close(pg_type_desc, AccessShareLock);
 
        return typeoid;
 }
@@ -248,7 +248,7 @@ TypeShellMake(char *typeName)
         *      open pg_type
         * ----------------
         */
-       pg_type_desc = heap_openr(TypeRelationName);
+       pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
 
        /* ----------------
         *      insert the shell tuple
@@ -260,7 +260,7 @@ TypeShellMake(char *typeName)
         *      close pg_type and return the tuple's oid.
         * ----------------
         */
-       heap_close(pg_type_desc);
+       heap_close(pg_type_desc, RowExclusiveLock);
 
        return typoid;
 }
@@ -457,14 +457,7 @@ TypeCreate(char *typeName,
         *      open pg_type and begin a scan for the type name.
         * ----------------
         */
-       pg_type_desc = heap_openr(TypeRelationName);
-
-       /* -----------------
-        * Set a write lock initially so as not upgrade a read to a write
-        * when the heap_insert() or heap_replace() is called.
-        * -----------------
-        */
-       LockRelation(pg_type_desc, AccessExclusiveLock);
+       pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
 
        typeKey[0].sk_argument = PointerGetDatum(typeName);
        pg_type_scan = heap_beginscan(pg_type_desc,
@@ -521,8 +514,8 @@ TypeCreate(char *typeName,
                CatalogIndexInsert(idescs, Num_pg_type_indices, pg_type_desc, tup);
                CatalogCloseIndices(Num_pg_type_indices, idescs);
        }
-       UnlockRelation(pg_type_desc, AccessExclusiveLock);
-       heap_close(pg_type_desc);
+
+       heap_close(pg_type_desc, RowExclusiveLock);
 
        return typeObjectId;
 }
@@ -541,7 +534,7 @@ TypeRename(char *oldTypeName, char *newTypeName)
        HeapTuple       oldtup,
                                newtup;
 
-       pg_type_desc = heap_openr(TypeRelationName);
+       pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
 
        oldtup = SearchSysCacheTupleCopy(TYPNAME,
                                                                         PointerGetDatum(oldTypeName),
@@ -549,7 +542,7 @@ TypeRename(char *oldTypeName, char *newTypeName)
 
        if (!HeapTupleIsValid(oldtup))
        {
-               heap_close(pg_type_desc);
+               heap_close(pg_type_desc, RowExclusiveLock);
                elog(ERROR, "TypeRename: type %s not defined", oldTypeName);
        }
 
@@ -559,7 +552,7 @@ TypeRename(char *oldTypeName, char *newTypeName)
        if (HeapTupleIsValid(newtup))
        {
                pfree(oldtup);
-               heap_close(pg_type_desc);
+               heap_close(pg_type_desc, RowExclusiveLock);
                elog(ERROR, "TypeRename: type %s already defined", newTypeName);
        }
 
@@ -575,7 +568,7 @@ TypeRename(char *oldTypeName, char *newTypeName)
        CatalogCloseIndices(Num_pg_type_indices, idescs);
 
        pfree(oldtup);
-       heap_close(pg_type_desc);
+       heap_close(pg_type_desc, RowExclusiveLock);
 }
 
 /*
index ebdd045ce4fa2a9c8fb9fbe3550557b38c07655c..f8196f86ab3e88b71ad95b2c246367269d271f5d 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.53 1999/07/18 18:03:49 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.54 1999/09/18 19:06:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  *       transaction, since by assumption it is only called from outside any
  *       transaction.
  *
- * Note that the system's use of pg_listener is confined to very short
- * intervals at the end of a transaction that contains NOTIFY statements,
- * or during the transaction caused by an inbound SIGUSR2.     So the fact that
- * pg_listener is a global resource shouldn't cause too much performance
- * problem.  But application authors ought to be discouraged from doing
- * LISTEN or UNLISTEN near the start of a long transaction --- that would
- * result in holding the pg_listener write lock for a long time, possibly
- * blocking unrelated activity.  It could even lead to deadlock against another
- * transaction that touches the same user tables and then tries to NOTIFY.
- * Probably best to do LISTEN or UNLISTEN outside of transaction blocks.
+ * Although we grab AccessExclusiveLock on pg_listener for any operation,
+ * the lock is never held very long, so it shouldn't cause too much of
+ * a performance problem.
  *
  * An application that listens on the same relname it notifies will get
  * NOTIFY messages for its own NOTIFYs.  These can be ignored, if not useful,
@@ -155,26 +148,21 @@ Async_Notify(char *relname)
 
        TPRINTF(TRACE_NOTIFY, "Async_Notify: %s", relname);
 
-       /*
-        * We allocate list memory from the global malloc pool to ensure that
-        * it will live until we want to use it.  This is probably not
-        * necessary any longer, since we will use it before the end of the
-        * transaction. DLList only knows how to use malloc() anyway, but we
-        * could probably palloc() the strings...
-        */
        if (!pendingNotifies)
                pendingNotifies = DLNewList();
-       notifyName = strdup(relname);
-       DLAddHead(pendingNotifies, DLNewElem(notifyName));
-
-       /*
-        * NOTE: we could check to see if pendingNotifies already has an entry
-        * for relname, and thus avoid making duplicate entries.  However,
-        * most apps probably don't notify the same name multiple times per
-        * transaction, so we'd likely just be wasting cycles to make such a
-        * check. AsyncExistsPendingNotify() doesn't really care whether the
-        * list contains duplicates...
-        */
+       /* no point in making duplicate entries in the list ... */
+       if (!AsyncExistsPendingNotify(relname))
+       {
+               /*
+                * We allocate list memory from the global malloc pool to ensure
+                * that it will live until we want to use it.  This is probably not
+                * necessary any longer, since we will use it before the end of the
+                * transaction. DLList only knows how to use malloc() anyway, but we
+                * could probably palloc() the strings...
+                */
+               notifyName = strdup(relname);
+               DLAddHead(pendingNotifies, DLNewElem(notifyName));
+       }
 }
 
 /*
@@ -212,8 +200,7 @@ Async_Listen(char *relname, int pid)
 
        TPRINTF(TRACE_NOTIFY, "Async_Listen: %s", relname);
 
-       lRel = heap_openr(ListenerRelationName);
-       LockRelation(lRel, AccessExclusiveLock);
+       lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
        tdesc = RelationGetDescr(lRel);
 
        /* Detect whether we are already listening on this relname */
@@ -236,9 +223,8 @@ Async_Listen(char *relname, int pid)
 
        if (alreadyListener)
        {
+               heap_close(lRel, AccessExclusiveLock);
                elog(NOTICE, "Async_Listen: We are already listening on %s", relname);
-               UnlockRelation(lRel, AccessExclusiveLock);
-               heap_close(lRel);
                return;
        }
 
@@ -262,8 +248,7 @@ Async_Listen(char *relname, int pid)
        heap_insert(lRel, newtup);
        pfree(newtup);
 
-       UnlockRelation(lRel, AccessExclusiveLock);
-       heap_close(lRel);
+       heap_close(lRel, AccessExclusiveLock);
 
        /*
         * now that we are listening, make sure we will unlisten before dying.
@@ -308,18 +293,14 @@ Async_Unlisten(char *relname, int pid)
 
        TPRINTF(TRACE_NOTIFY, "Async_Unlisten %s", relname);
 
+       lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
        /* Note we assume there can be only one matching tuple. */
        lTuple = SearchSysCacheTuple(LISTENREL, PointerGetDatum(relname),
                                                                 Int32GetDatum(pid),
                                                                 0, 0);
        if (lTuple != NULL)
-       {
-               lRel = heap_openr(ListenerRelationName);
-               LockRelation(lRel, AccessExclusiveLock);
                heap_delete(lRel, &lTuple->t_self, NULL);
-               UnlockRelation(lRel, AccessExclusiveLock);
-               heap_close(lRel);
-       }
+       heap_close(lRel, AccessExclusiveLock);
 
        /*
         * We do not complain about unlistening something not being listened;
@@ -354,8 +335,7 @@ Async_UnlistenAll()
 
        TPRINTF(TRACE_NOTIFY, "Async_UnlistenAll");
 
-       lRel = heap_openr(ListenerRelationName);
-       LockRelation(lRel, AccessExclusiveLock);
+       lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
        tdesc = RelationGetDescr(lRel);
 
        /* Find and delete all entries with my listenerPID */
@@ -369,8 +349,7 @@ Async_UnlistenAll()
                heap_delete(lRel, &lTuple->t_self, NULL);
 
        heap_endscan(sRel);
-       UnlockRelation(lRel, AccessExclusiveLock);
-       heap_close(lRel);
+       heap_close(lRel, AccessExclusiveLock);
 }
 
 /*
@@ -462,8 +441,7 @@ AtCommit_Notify()
 
        TPRINTF(TRACE_NOTIFY, "AtCommit_Notify");
 
-       lRel = heap_openr(ListenerRelationName);
-       LockRelation(lRel, AccessExclusiveLock);
+       lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
        tdesc = RelationGetDescr(lRel);
        sRel = heap_beginscan(lRel, 0, SnapshotNow, 0, (ScanKey) NULL);
 
@@ -542,10 +520,13 @@ AtCommit_Notify()
        heap_endscan(sRel);
 
        /*
-        * We do not do RelationUnsetLockForWrite(lRel) here, because the
-        * transaction is about to be committed anyway.
+        * We do NOT release the lock on pg_listener here; we need to hold it
+        * until end of transaction (which is about to happen, anyway) to
+        * ensure that notified backends see our tuple updates when they look.
+        * Else they might disregard the signal, which would make the
+        * application programmer very unhappy.
         */
-       heap_close(lRel);
+       heap_close(lRel, NoLock);
 
        ClearPendingNotifies();
 
@@ -756,8 +737,7 @@ ProcessIncomingNotify(void)
 
        StartTransactionCommand();
 
-       lRel = heap_openr(ListenerRelationName);
-       LockRelation(lRel, AccessExclusiveLock);
+       lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
        tdesc = RelationGetDescr(lRel);
 
        /* Scan only entries with my listenerPID */
@@ -794,10 +774,13 @@ ProcessIncomingNotify(void)
        heap_endscan(sRel);
 
        /*
-        * We do not do RelationUnsetLockForWrite(lRel) here, because the
-        * transaction is about to be committed anyway.
+        * We do NOT release the lock on pg_listener here; we need to hold it
+        * until end of transaction (which is about to happen, anyway) to
+        * ensure that other backends see our tuple updates when they look.
+        * Otherwise, a transaction started after this one might mistakenly
+        * think it doesn't need to send this backend a new NOTIFY.
         */
-       heap_close(lRel);
+       heap_close(lRel, NoLock);
 
        CommitTransactionCommand();
 
index 6f99a920f5a3ec5a69dda786bc090f9eda7fe2bc..d578fc263f030aa4ccd6904bec26b2bb9e2a7848 100644 (file)
@@ -14,7 +14,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.44 1999/07/17 20:16:51 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.45 1999/09/18 19:06:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -101,29 +101,20 @@ cluster(char *oldrelname, char *oldindexname)
 
        /*
         * Like vacuum, cluster spans transactions, so I'm going to handle it
-        * in the same way.
+        * in the same way: commit and restart transactions where needed.
+        *
+        * We grab exclusive access to the target rel and index for the
+        * duration of the initial transaction.
         */
 
-       /* matches the StartTransaction in PostgresMain() */
-
-       OldHeap = heap_openr(oldrelname);
-       if (!RelationIsValid(OldHeap))
-       {
-               elog(ERROR, "cluster: unknown relation: \"%s\"",
-                        oldrelname);
-       }
-       OIDOldHeap = RelationGetRelid(OldHeap);         /* Get OID for the index
-                                                                                                * scan    */
+       OldHeap = heap_openr(oldrelname, AccessExclusiveLock);
+       OIDOldHeap = RelationGetRelid(OldHeap);
 
        OldIndex = index_openr(oldindexname);           /* Open old index relation      */
-       if (!RelationIsValid(OldIndex))
-       {
-               elog(ERROR, "cluster: unknown index: \"%s\"",
-                        oldindexname);
-       }
-       OIDOldIndex = RelationGetRelid(OldIndex);       /* OID for the index scan                 */
+       LockRelation(OldIndex, AccessExclusiveLock);
+       OIDOldIndex = RelationGetRelid(OldIndex);
 
-       heap_close(OldHeap);
+       heap_close(OldHeap, NoLock); /* do NOT give up the locks */
        index_close(OldIndex);
 
        /*
@@ -132,7 +123,7 @@ cluster(char *oldrelname, char *oldindexname)
         * will get the lock after being blocked and add rows which won't be
         * present in the new table. Bleagh! I'd be best to try and ensure
         * that no-one's in the tables for the entire duration of this process
-        * with a pg_vlock.
+        * with a pg_vlock.  XXX Isn't the above comment now invalid?
         */
        NewHeap = copy_heap(OIDOldHeap);
        OIDNewHeap = RelationGetRelid(NewHeap);
@@ -171,7 +162,7 @@ cluster(char *oldrelname, char *oldindexname)
        renamerel(NewIndexName, saveoldindexname);
 
        /*
-        * Again flush all the buffers.
+        * Again flush all the buffers.  XXX perhaps not needed?
         */
        CommitTransactionCommand();
        StartTransactionCommand();
@@ -193,7 +184,7 @@ copy_heap(Oid OIDOldHeap)
         */
        snprintf(NewName, NAMEDATALEN, "temp_%x", OIDOldHeap);
 
-       OldHeap = heap_open(OIDOldHeap);
+       OldHeap = heap_open(OIDOldHeap, AccessExclusiveLock);
        OldHeapDesc = RelationGetDescr(OldHeap);
 
        /*
@@ -209,10 +200,11 @@ copy_heap(Oid OIDOldHeap)
        if (!OidIsValid(OIDNewHeap))
                elog(ERROR, "clusterheap: cannot create temporary heap relation\n");
 
-       NewHeap = heap_open(OIDNewHeap);
+       /* XXX why are we bothering to do this: */
+       NewHeap = heap_open(OIDNewHeap, AccessExclusiveLock);
 
-       heap_close(NewHeap);
-       heap_close(OldHeap);
+       heap_close(NewHeap, AccessExclusiveLock);
+       heap_close(OldHeap, AccessExclusiveLock);
 
        return NewHeap;
 }
@@ -233,7 +225,7 @@ copy_index(Oid OIDOldIndex, Oid OIDNewHeap)
        int                     natts;
        FuncIndexInfo *finfo;
 
-       NewHeap = heap_open(OIDNewHeap);
+       NewHeap = heap_open(OIDNewHeap, AccessExclusiveLock);
        OldIndex = index_open(OIDOldIndex);
 
        /*
@@ -305,8 +297,8 @@ copy_index(Oid OIDOldIndex, Oid OIDNewHeap)
                                 Old_pg_index_Form->indisunique,
                                 Old_pg_index_Form->indisprimary);
 
-       heap_close(OldIndex);
-       heap_close(NewHeap);
+       index_close(OldIndex);
+       heap_close(NewHeap, AccessExclusiveLock);
 }
 
 
@@ -326,8 +318,8 @@ rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
         * Open the relations I need. Scan through the OldHeap on the OldIndex
         * and insert each tuple into the NewHeap.
         */
-       LocalNewHeap = (Relation) heap_open(OIDNewHeap);
-       LocalOldHeap = (Relation) heap_open(OIDOldHeap);
+       LocalNewHeap = heap_open(OIDNewHeap, AccessExclusiveLock);
+       LocalOldHeap = heap_open(OIDOldHeap, AccessExclusiveLock);
        LocalOldIndex = (Relation) index_open(OIDOldIndex);
 
        ScanDesc = index_beginscan(LocalOldIndex, false, 0, (ScanKey) NULL);
@@ -344,6 +336,6 @@ rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
        index_endscan(ScanDesc);
 
        index_close(LocalOldIndex);
-       heap_close(LocalOldHeap);
-       heap_close(LocalNewHeap);
+       heap_close(LocalOldHeap, AccessExclusiveLock);
+       heap_close(LocalNewHeap, AccessExclusiveLock);
 }
index 7fe62cf1246b1937908b5c1df0976516dcdec1c3..8872bcdfac72ab79a8682c12256a87c8a0eeed60 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.53 1999/09/04 21:19:33 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.54 1999/09/18 19:06:40 tgl Exp $
  *
  * NOTES
  *       The PortalExecutorHeapMemory crap needs to be eliminated
@@ -283,6 +283,7 @@ PerformAddAttribute(char *relationName,
 {
        Relation        rel,
                                attrdesc;
+       Oid                     myrelid;
        HeapTuple       reltup;
        HeapTuple       attributeTuple;
        Form_pg_attribute attribute;
@@ -310,6 +311,14 @@ PerformAddAttribute(char *relationName,
                         relationName);
 #endif
 
+       /*
+        * Grab an exclusive lock on the target table, which we will NOT release
+        * until end of transaction.
+        */
+       rel = heap_openr(relationName, AccessExclusiveLock);
+       myrelid = RelationGetRelid(rel);
+       heap_close(rel, NoLock);        /* close rel but keep lock! */
+
        /*
         * we can't add a not null attribute
         */
@@ -331,20 +340,10 @@ PerformAddAttribute(char *relationName,
        {
                if (inherits)
                {
-                       Oid                     myrelid,
-                                               childrelid;
+                       Oid                     childrelid;
                        List       *child,
                                           *children;
 
-                       rel = heap_openr(relationName);
-                       if (!RelationIsValid(rel))
-                       {
-                               elog(ERROR, "PerformAddAttribute: unknown relation: \"%s\"",
-                                        relationName);
-                       }
-                       myrelid = RelationGetRelid(rel);
-                       heap_close(rel);
-
                        /* this routine is actually in the planner */
                        children = find_all_inheritors(lconsi(myrelid, NIL), NIL);
 
@@ -358,31 +357,23 @@ PerformAddAttribute(char *relationName,
                                childrelid = lfirsti(child);
                                if (childrelid == myrelid)
                                        continue;
-                               rel = heap_open(childrelid);
-                               if (!RelationIsValid(rel))
-                               {
-                                       elog(ERROR, "PerformAddAttribute: can't find catalog entry for inheriting class with oid %u",
-                                                childrelid);
-                               }
+                               rel = heap_open(childrelid, AccessExclusiveLock);
                                PerformAddAttribute((rel->rd_rel->relname).data,
                                                                        userName, false, colDef);
-                               heap_close(rel);
+                               heap_close(rel, AccessExclusiveLock);
                        }
                }
        }
 
-       rel = heap_openr(RelationRelationName);
+       rel = heap_openr(RelationRelationName, RowExclusiveLock);
 
        reltup = SearchSysCacheTupleCopy(RELNAME,
                                                                         PointerGetDatum(relationName),
                                                                         0, 0, 0);
 
        if (!HeapTupleIsValid(reltup))
-       {
-               heap_close(rel);
                elog(ERROR, "PerformAddAttribute: relation \"%s\" not found",
                         relationName);
-       }
 
        /*
         * XXX is the following check sufficient?
@@ -391,23 +382,15 @@ PerformAddAttribute(char *relationName,
        {
                elog(ERROR, "PerformAddAttribute: index relation \"%s\" not changed",
                         relationName);
-               return;
        }
 
        minattnum = ((Form_pg_class) GETSTRUCT(reltup))->relnatts;
        maxatts = minattnum + 1;
        if (maxatts > MaxHeapAttributeNumber)
-       {
-               pfree(reltup);
-               heap_close(rel);
                elog(ERROR, "PerformAddAttribute: relations limited to %d attributes",
                         MaxHeapAttributeNumber);
-       }
-
-       attrdesc = heap_openr(AttributeRelationName);
 
-       Assert(attrdesc);
-       Assert(RelationGetForm(attrdesc));
+       attrdesc = heap_openr(AttributeRelationName, RowExclusiveLock);
 
        /*
         * Open all (if any) pg_attribute indices
@@ -438,12 +421,8 @@ PerformAddAttribute(char *relationName,
                                                                  0, 0);
 
                if (HeapTupleIsValid(tup))
-               {
-                       heap_close(attrdesc);
-                       heap_close(rel);
                        elog(ERROR, "PerformAddAttribute: attribute \"%s\" already exists in class \"%s\"",
                                 colDef->colname, relationName);
-               }
 
                /*
                 * check to see if it is an array attribute.
@@ -490,7 +469,8 @@ PerformAddAttribute(char *relationName,
 
        if (hasindex)
                CatalogCloseIndices(Num_pg_attr_indices, idescs);
-       heap_close(attrdesc);
+
+       heap_close(attrdesc, RowExclusiveLock);
 
        ((Form_pg_class) GETSTRUCT(reltup))->relnatts = maxatts;
        heap_replace(rel, &reltup->t_self, reltup, NULL);
@@ -501,7 +481,7 @@ PerformAddAttribute(char *relationName,
        CatalogCloseIndices(Num_pg_class_indices, ridescs);
 
        pfree(reltup);
-       heap_close(rel);
+       heap_close(rel, RowExclusiveLock);
 }
 
 void
@@ -510,9 +490,9 @@ LockTableCommand(LockStmt *lockstmt)
        Relation        rel;
        int                     aclresult;
 
-       rel = heap_openr(lockstmt->relname);
-       if (rel == NULL)
-               elog(ERROR, "LOCK TABLE: relation %s can't be openned", lockstmt->relname);
+       rel = heap_openr(lockstmt->relname, NoLock);
+       if (! RelationIsValid(rel))
+               elog(ERROR, "Relation '%s' does not exist", lockstmt->relname);
 
        if (lockstmt->mode == AccessShareLock)
                aclresult = pg_aclcheck(lockstmt->relname, GetPgUserName(), ACL_RD);
@@ -524,4 +504,5 @@ LockTableCommand(LockStmt *lockstmt)
 
        LockRelation(rel, lockstmt->mode);
 
+       heap_close(rel, NoLock);        /* close rel, keep lock */
 }
index 35f3d6da0b31470ac617aa0b01fb98a2a353886b..493d2a170e10662ba23b337e0883cd9698cce6a6 100644 (file)
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.87 1999/09/11 22:28:11 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.88 1999/09/18 19:06:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -251,22 +251,22 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
        Relation        rel;
        extern char *UserName;          /* defined in global.c */
        const AclMode required_access = from ? ACL_WR : ACL_RD;
+       LOCKMODE        required_lock = from ? AccessExclusiveLock : AccessShareLock;
+       /* Note: AccessExclusive is probably overkill for copying to a relation,
+        * but that's what the existing code grabs on the rel's indices.  If
+        * this is relaxed then I think the index locks need relaxed also.
+        */
        int                     result;
 
-       rel = heap_openr(relname);
-       if (rel == NULL)
-               elog(ERROR, "COPY command failed.  Class %s "
-                        "does not exist.", relname);
+       rel = heap_openr(relname, required_lock);
 
        result = pg_aclcheck(relname, UserName, required_access);
        if (result != ACLCHECK_OK)
                elog(ERROR, "%s: %s", relname, aclcheck_error_strings[result]);
-       /* Above should not return */
-       else if (!superuser() && !pipe)
+       else if (!pipe && !superuser())
                elog(ERROR, "You must have Postgres superuser privilege to do a COPY "
                         "directly to or from a file.  Anyone can COPY to stdout or "
                         "from stdin.  Psql's \\copy command also works for anyone.");
-       /* Above should not return. */
        else
        {
                if (from)
@@ -342,6 +342,8 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
                                pq_endcopyout(false);
                }
        }
+
+       heap_close(rel, required_lock);
 }
 
 
@@ -500,8 +502,6 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
                pfree(elements);
                pfree(typmod);
        }
-
-       heap_close(rel);
 }
 
 static void
@@ -905,20 +905,19 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
                pfree(typmod);
        }
 
-       /* comments in execUtils.c */
        if (has_index)
        {
                for (i = 0; i < n_indices; i++)
                {
                        if (index_rels[i] == NULL)
                                continue;
+                       /* see comments in ExecOpenIndices() in execUtils.c */
                        if ((index_rels[i])->rd_rel->relam != BTREE_AM_OID &&
                                (index_rels[i])->rd_rel->relam != HASH_AM_OID)
                                UnlockRelation(index_rels[i], AccessExclusiveLock);
                        index_close(index_rels[i]);
                }
        }
-       heap_close(rel);
 }
 
 
@@ -991,7 +990,7 @@ IsTypeByVal(Oid type)
 /*
  * Given the OID of a relation, return an array of index relation descriptors
  * and the number of index relations.  These relation descriptors are open
- * using heap_open().
+ * using index_open().
  *
  * Space for the array itself is palloc'ed.
  */
@@ -1017,7 +1016,7 @@ GetIndexRelations(Oid main_relation_oid,
        int                     i;
        bool            isnull;
 
-       pg_index_rel = heap_openr(IndexRelationName);
+       pg_index_rel = heap_openr(IndexRelationName, AccessShareLock);
        scandesc = heap_beginscan(pg_index_rel, 0, SnapshotNow, 0, NULL);
        tupDesc = RelationGetDescr(pg_index_rel);
 
@@ -1044,7 +1043,7 @@ GetIndexRelations(Oid main_relation_oid,
        }
 
        heap_endscan(scandesc);
-       heap_close(pg_index_rel);
+       heap_close(pg_index_rel, AccessShareLock);
 
        /* We cannot trust to relhasindex of the main_relation now, so... */
        if (*n_indices == 0)
@@ -1055,7 +1054,7 @@ GetIndexRelations(Oid main_relation_oid,
        for (i = 0, scan = head; i < *n_indices; i++, scan = scan->next)
        {
                (*index_rels)[i] = index_open(scan->index_rel_oid);
-               /* comments in execUtils.c */
+               /* see comments in ExecOpenIndices() in execUtils.c */
                if ((*index_rels)[i] != NULL &&
                        ((*index_rels)[i])->rd_rel->relam != BTREE_AM_OID &&
                        ((*index_rels)[i])->rd_rel->relam != HASH_AM_OID)
index b93a40e7ba326629e1f7981aa1f1f2d400c736cd..c1069dd41e6948f78d576be7a07c9b22f428c8ed 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.45 1999/07/17 20:16:52 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.46 1999/09/18 19:06:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -202,14 +202,13 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
         */
        foreach(entry, schema)
        {
-               List       *rest;
                ColumnDef  *coldef = lfirst(entry);
+               List       *rest;
 
                foreach(rest, lnext(entry))
                {
-
                        /*
-                        * check for duplicated relation names
+                        * check for duplicated names within the new relation
                         */
                        ColumnDef  *restdef = lfirst(rest);
 
@@ -246,17 +245,14 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
                TupleDesc       tupleDesc;
                TupleConstr *constr;
 
-               relation = heap_openr(name);
-               if (relation == NULL)
-               {
-                       elog(ERROR,
-                                "MergeAttr: Can't inherit from non-existent superclass '%s'", name);
-               }
-               if (relation->rd_rel->relkind == 'S')
-                       elog(ERROR, "MergeAttr: Can't inherit from sequence superclass '%s'", name);
+               relation = heap_openr(name, AccessShareLock);
                tupleDesc = RelationGetDescr(relation);
                constr = tupleDesc->constr;
 
+               /* XXX shouldn't this test be stricter?  No indexes, for example? */
+               if (relation->rd_rel->relkind == 'S')
+                       elog(ERROR, "MergeAttr: Can't inherit from sequence superclass '%s'", name);
+
                for (attrno = relation->rd_rel->relnatts - 1; attrno >= 0; attrno--)
                {
                        Form_pg_attribute attribute = tupleDesc->attrs[attrno];
@@ -340,9 +336,11 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
                }
 
                /*
-                * iteration cleanup and result collection
+                * Close the parent rel, but keep our AccessShareLock on it until
+                * xact commit.  That will prevent someone else from deleting or
+                * ALTERing the parent before the child is committed.
                 */
-               heap_close(relation);
+               heap_close(relation, NoLock);
 
                /*
                 * wants the inherited schema to appear in the order they are
@@ -386,7 +384,7 @@ StoreCatalogInheritance(Oid relationId, List *supers)
         * Catalog INHERITS information.
         * ----------------
         */
-       relation = heap_openr(InheritsRelationName);
+       relation = heap_openr(InheritsRelationName, RowExclusiveLock);
        desc = RelationGetDescr(relation);
 
        seqNumber = 1;
@@ -422,7 +420,7 @@ StoreCatalogInheritance(Oid relationId, List *supers)
                seqNumber += 1;
        }
 
-       heap_close(relation);
+       heap_close(relation, RowExclusiveLock);
 
        /* ----------------
         * Catalog IPL information.
@@ -510,7 +508,7 @@ again:
         *      3.
         * ----------------
         */
-       relation = heap_openr(InheritancePrecidenceListRelationName);
+       relation = heap_openr(InheritancePrecidenceListRelationName, RowExclusiveLock);
        desc = RelationGetDescr(relation);
 
        seqNumber = 1;
@@ -537,7 +535,7 @@ again:
                seqNumber += 1;
        }
 
-       heap_close(relation);
+       heap_close(relation, RowExclusiveLock);
 }
 
 /*
index b779715fe8e3863847ffccffa656c7dc35294b8e..24eb5b531d392f4a014a965951aacf68f582b5a4 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.39 1999/07/17 20:16:52 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.40 1999/09/18 19:06:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -103,6 +103,8 @@ destroydb(char *dbname, CommandDest dest)
        /* stop the vacuum daemon */
        stop_vacuum(dbpath, dbname);
 
+       /* XXX what about stopping backends connected to the target database? */
+
        path = ExpandDatabasePath(dbpath);
        if (path == NULL)
                elog(ERROR, "Unable to locate path '%s'"
@@ -189,6 +191,7 @@ check_permissions(char *command,
        utup = SearchSysCacheTuple(USENAME,
                                                           PointerGetDatum(userName),
                                                           0, 0, 0);
+       Assert(utup);
        *userIdP = ((Form_pg_shadow) GETSTRUCT(utup))->usesysid;
        use_super = ((Form_pg_shadow) GETSTRUCT(utup))->usesuper;
        use_createdb = ((Form_pg_shadow) GETSTRUCT(utup))->usecreatedb;
@@ -211,22 +214,13 @@ check_permissions(char *command,
        /* Check to make sure database is owned by this user */
 
        /*
-        * need the reldesc to get the database owner out of dbtup and to set
-        * a write lock on it.
+        * Acquire exclusive lock on pg_database from the beginning, even though
+        * we only need read access right here, to avoid potential deadlocks
+        * from upgrading our lock later.  (Is this still necessary?  Could we
+        * use something weaker than exclusive lock?)
         */
-       dbrel = heap_openr(DatabaseRelationName);
-
-       if (!RelationIsValid(dbrel))
-               elog(FATAL, "%s: cannot open relation \"%-.*s\"",
-                        command, DatabaseRelationName);
+       dbrel = heap_openr(DatabaseRelationName, AccessExclusiveLock);
 
-       /*
-        * Acquire a write lock on pg_database from the beginning to avoid
-        * upgrading a read lock to a write lock.  Upgrading causes long
-        * delays when multiple 'createdb's or 'destroydb's are run simult.
-        * -mer 7/3/91
-        */
-       LockRelation(dbrel, AccessExclusiveLock);
        dbtup = get_pg_dbtup(command, dbname, dbrel);
        dbfound = HeapTupleIsValid(dbtup);
 
@@ -248,7 +242,8 @@ check_permissions(char *command,
        else
                *dbIdP = InvalidOid;
 
-       heap_close(dbrel);
+       /* We will keep the lock on dbrel until end of transaction. */
+       heap_close(dbrel, NoLock);
 
        /*
         * Now be sure that the user is allowed to do this.
index 3b1da18783dad53e12e926077ba588938eaa993a..11e5c39423918fa3ba8081eff5e4ae95647698c8 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Copyright (c) 1994-5, Regents of the University of California
  *
- *       $Id: explain.c,v 1.47 1999/09/11 19:06:36 tgl Exp $
+ *       $Id: explain.c,v 1.48 1999/09/18 19:06:40 tgl Exp $
  *
  */
 
@@ -211,11 +211,14 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es)
                        i = 0;
                        foreach(l, ((IndexScan *) plan)->indxid)
                        {
-                               relation = RelationIdCacheGetRelation((int) lfirst(l));
+                               relation = RelationIdGetRelation(lfirsti(l));
+                               Assert(relation);
                                if (++i > 1)
                                        appendStringInfo(str, ", ");
                                appendStringInfo(str,
                                                                 stringStringInfo((RelationGetRelationName(relation))->data));
+                               /* drop relcache refcount from RelationIdGetRelation */
+                               RelationDecrementReferenceCount(relation);
                        }
                case T_SeqScan:
                        if (((Scan *) plan)->scanrelid > 0)
index 31d3419bee671b5e2773ca7d6368dfcabd75d800..113854311d6aaf22b855fd59077154e7f3241812 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.10 1999/08/22 20:14:37 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.11 1999/09/18 19:06:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -324,15 +324,15 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
                FIsetProcOid(funcInfo, tuple->t_data->t_oid);
        }
 
-       heapRelation = heap_open(relationId);
+       heapRelation = heap_open(relationId, ShareLock);
        indexRelation = index_open(indexId);
 
-       LockRelation(heapRelation, ShareLock);
-
        InitIndexStrategy(numberOfAttributes, indexRelation, accessMethodId);
 
        index_build(heapRelation, indexRelation, numberOfAttributes,
                                attributeNumberA, 0, NULL, funcInfo, predInfo);
+
+       /* heap and index rels are closed as a side-effect of index_build */
 }
 
 
index 21fde2af57997bbceeb1d8280f61d6e6c2a432a0..b2fc76f090bc0b0fd60d249b73c2e2e6a03cb164 100644 (file)
@@ -120,15 +120,14 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
        values[i++] = ObjectIdGetDatum(procTup->t_data->t_oid);
        values[i++] = (Datum) fmgr(F_TEXTIN, stmt->plcompiler);
 
-       rel = heap_openr(LanguageRelationName);
+       rel = heap_openr(LanguageRelationName, RowExclusiveLock);
 
        tupDesc = rel->rd_att;
        tup = heap_formtuple(tupDesc, values, nulls);
 
        heap_insert(rel, tup);
 
-       heap_close(rel);
-       return;
+       heap_close(rel, RowExclusiveLock);
 }
 
 
@@ -160,6 +159,8 @@ DropProceduralLanguage(DropPLangStmt *stmt)
         */
        case_translate_language_name(stmt->plname, languageName);
 
+       rel = heap_openr(LanguageRelationName, RowExclusiveLock);
+
        langTup = SearchSysCacheTupleCopy(LANNAME,
                                                                          PointerGetDatum(languageName),
                                                                          0, 0, 0);
@@ -167,14 +168,11 @@ DropProceduralLanguage(DropPLangStmt *stmt)
                elog(ERROR, "Language %s doesn't exist", languageName);
 
        if (!((Form_pg_language) GETSTRUCT(langTup))->lanispl)
-       {
                elog(ERROR, "Language %s isn't a created procedural language",
                         languageName);
-       }
 
-       rel = heap_openr(LanguageRelationName);
        heap_delete(rel, &langTup->t_self, NULL);
 
        pfree(langTup);
-       heap_close(rel);
+       heap_close(rel, RowExclusiveLock);
 }
index af20c79f17db8a7b13a7bac6ffa5d71efe8cc30a..a73964cb02c3b1908afa842afdb31865b667c13b 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.36 1999/07/17 20:16:53 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.37 1999/09/18 19:06:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -75,13 +75,14 @@ RemoveOperator(char *operatorName,          /* operator name */
        else
                oprtype = 'r';
 
+       relation = heap_openr(OperatorRelationName, RowExclusiveLock);
+
        tup = SearchSysCacheTupleCopy(OPRNAME,
                                                                  PointerGetDatum(operatorName),
                                                                  ObjectIdGetDatum(typeId1),
                                                                  ObjectIdGetDatum(typeId2),
                                                                  CharGetDatum(oprtype));
 
-       relation = heap_openr(OperatorRelationName);
        if (HeapTupleIsValid(tup))
        {
 #ifndef NO_SECURITY
@@ -117,7 +118,7 @@ RemoveOperator(char *operatorName,          /* operator name */
                }
        }
        pfree(tup);
-       heap_close(relation);
+       heap_close(relation, RowExclusiveLock);
 }
 
 #ifdef NOTYET
@@ -141,7 +142,7 @@ SingleOpOperatorRemove(Oid typeOid)
 
        ScanKeyEntryInitialize(&key[0],
                                                   0, 0, F_OIDEQ, (Datum) typeOid);
-       rel = heap_openr(OperatorRelationName);
+       rel = heap_openr(OperatorRelationName, RowExclusiveLock);
        for (i = 0; i < 3; ++i)
        {
                key[0].sk_attno = attnums[i];
@@ -150,7 +151,7 @@ SingleOpOperatorRemove(Oid typeOid)
                        heap_delete(rel, &tup->t_self, NULL);
                heap_endscan(scan);
        }
-       heap_close(rel);
+       heap_close(rel, RowExclusiveLock);
 }
 
 /*
@@ -187,7 +188,7 @@ AttributeAndRelationRemove(Oid typeOid)
        oidptr = (struct oidlist *) palloc(sizeof(*oidptr));
        oidptr->next = NULL;
        optr = oidptr;
-       rel = heap_openr(AttributeRelationName);
+       rel = heap_openr(AttributeRelationName, AccessShareLock);
        scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
        while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
        {
@@ -197,14 +198,15 @@ AttributeAndRelationRemove(Oid typeOid)
        }
        optr->next = NULL;
        heap_endscan(scan);
-       heap_close(rel);
+       heap_close(rel, AccessShareLock);
 
+       optr = oidptr;
 
        ScanKeyEntryInitialize(&key[0], 0,
                                                   ObjectIdAttributeNumber,
                                                   F_OIDEQ, (Datum) 0);
-       optr = oidptr;
-       rel = heap_openr(RelationRelationName);
+       /* get RowExclusiveLock because heap_destroy will need it */
+       rel = heap_openr(RelationRelationName, RowExclusiveLock);
        while (PointerIsValid((char *) optr->next))
        {
                key[0].sk_argument = (Datum) (optr++)->reloid;
@@ -217,9 +219,9 @@ AttributeAndRelationRemove(Oid typeOid)
                        name = (((Form_pg_class) GETSTRUCT(tup))->relname).data;
                        heap_destroy_with_catalog(name);
                }
+               heap_endscan(scan);
        }
-       heap_endscan(scan);
-       heap_close(rel);
+       heap_close(rel, RowExclusiveLock);
 }
 
 #endif  /* NOTYET */
@@ -245,18 +247,17 @@ RemoveType(char *typeName)                /* type name to be removed */
                         typeName);
 #endif
 
-       relation = heap_openr(TypeRelationName);
+       relation = heap_openr(TypeRelationName, RowExclusiveLock);
+
        tup = SearchSysCacheTuple(TYPNAME,
                                                          PointerGetDatum(typeName),
                                                          0, 0, 0);
-
        if (!HeapTupleIsValid(tup))
        {
-               heap_close(relation);
+               heap_close(relation, RowExclusiveLock);
                elog(ERROR, "RemoveType: type '%s' does not exist", typeName);
        }
 
-       relation = heap_openr(TypeRelationName);
        typeOid = tup->t_data->t_oid;
        heap_delete(relation, &tup->t_self, NULL);
 
@@ -267,14 +268,13 @@ RemoveType(char *typeName)                /* type name to be removed */
                                                          0, 0, 0);
        if (!HeapTupleIsValid(tup))
        {
-               heap_close(relation);
-               elog(ERROR, "RemoveType: type '%s' does not exist", typeName);
+               heap_close(relation, RowExclusiveLock);
+               elog(ERROR, "RemoveType: type '%s' does not exist", shadow_type);
        }
 
-       typeOid = tup->t_data->t_oid;
        heap_delete(relation, &tup->t_self, NULL);
 
-       heap_close(relation);
+       heap_close(relation, RowExclusiveLock);
 }
 
 /*
@@ -328,7 +328,7 @@ RemoveFunction(char *functionName,          /* function name to be removed */
        }
 #endif
 
-       relation = heap_openr(ProcedureRelationName);
+       relation = heap_openr(ProcedureRelationName, RowExclusiveLock);
        tup = SearchSysCacheTuple(PRONAME,
                                                          PointerGetDatum(functionName),
                                                          Int32GetDatum(nargs),
@@ -337,19 +337,19 @@ RemoveFunction(char *functionName,                /* function name to be removed */
 
        if (!HeapTupleIsValid(tup))
        {
-               heap_close(relation);
+               heap_close(relation, RowExclusiveLock);
                func_error("RemoveFunction", functionName, nargs, argList, NULL);
        }
 
        if ((((Form_pg_proc) GETSTRUCT(tup))->prolang) == INTERNALlanguageId)
        {
-               heap_close(relation);
+               heap_close(relation, RowExclusiveLock);
                elog(ERROR, "RemoveFunction: function \"%s\" is built-in", functionName);
        }
 
        heap_delete(relation, &tup->t_self, NULL);
 
-       heap_close(relation);
+       heap_close(relation, RowExclusiveLock);
 }
 
 void
@@ -398,7 +398,7 @@ RemoveAggregate(char *aggName, char *aggType)
        }
 #endif
 
-       relation = heap_openr(AggregateRelationName);
+       relation = heap_openr(AggregateRelationName, RowExclusiveLock);
        tup = SearchSysCacheTuple(AGGNAME,
                                                          PointerGetDatum(aggName),
                                                          ObjectIdGetDatum(basetypeID),
@@ -406,7 +406,7 @@ RemoveAggregate(char *aggName, char *aggType)
 
        if (!HeapTupleIsValid(tup))
        {
-               heap_close(relation);
+               heap_close(relation, RowExclusiveLock);
                if (aggType)
                {
                        elog(ERROR, "RemoveAggregate: aggregate '%s' for '%s' does not exist",
@@ -420,5 +420,5 @@ RemoveAggregate(char *aggName, char *aggType)
        }
        heap_delete(relation, &tup->t_self, NULL);
 
-       heap_close(relation);
+       heap_close(relation, RowExclusiveLock);
 }
index 1a93027b4a3c412e47047c0461b1e50cac26dfd1..3a822bd4e49ce6c2782440124fa3657b8a201460 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.32 1999/07/17 20:16:53 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.33 1999/09/18 19:06:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -48,6 +48,7 @@ renameatt(char *relname,
                  char *userName,
                  int recurse)
 {
+       Relation        targetrelation;
        Relation        attrelation;
        HeapTuple       reltup,
                                oldatttup,
@@ -71,6 +72,14 @@ renameatt(char *relname,
                         relname);
 #endif
 
+       /*
+        * Grab an exclusive lock on the target table, which we will NOT release
+        * until end of transaction.
+        */
+       targetrelation = heap_openr(relname, AccessExclusiveLock);
+       relid = RelationGetRelid(targetrelation);
+       heap_close(targetrelation, NoLock);     /* close rel but keep lock! */
+
        /*
         * if the 'recurse' flag is set then we are supposed to rename this
         * attribute in all classes that inherit from 'relname' (as well as in
@@ -82,16 +91,11 @@ renameatt(char *relname,
         */
        if (recurse)
        {
-               Oid                     myrelid,
-                                       childrelid;
                List       *child,
                                   *children;
 
-               if ((myrelid = RelnameFindRelid(relname)) == InvalidOid)
-                       elog(ERROR, "renameatt: unknown relation: \"%s\"", relname);
-
                /* this routine is actually in the planner */
-               children = find_all_inheritors(lconsi(myrelid, NIL), NIL);
+               children = find_all_inheritors(lconsi(relid, NIL), NIL);
 
                /*
                 * find_all_inheritors does the recursive search of the
@@ -100,10 +104,11 @@ renameatt(char *relname,
                 */
                foreach(child, children)
                {
+                       Oid                     childrelid;
                        char            childname[NAMEDATALEN];
 
                        childrelid = lfirsti(child);
-                       if (childrelid == myrelid)
+                       if (childrelid == relid)
                                continue;
                        reltup = SearchSysCacheTuple(RELOID,
                                                                                 ObjectIdGetDatum(childrelid),
@@ -117,14 +122,12 @@ renameatt(char *relname,
                        StrNCpy(childname,
                                        ((Form_pg_class) GETSTRUCT(reltup))->relname.data,
                                        NAMEDATALEN);
-                       /* no more recursion! */
+                       /* note we need not recurse again! */
                        renameatt(childname, oldattname, newattname, userName, 0);
                }
        }
 
-
-       if ((relid = RelnameFindRelid(relname)) == InvalidOid)
-               elog(ERROR, "renameatt: relation \"%s\" nonexistent", relname);
+       attrelation = heap_openr(AttributeRelationName, RowExclusiveLock);
 
        oldatttup = SearchSysCacheTupleCopy(ATTNAME,
                                                                                ObjectIdGetDatum(relid),
@@ -150,7 +153,6 @@ renameatt(char *relname,
        StrNCpy((((Form_pg_attribute) (GETSTRUCT(oldatttup)))->attname.data),
                        newattname, NAMEDATALEN);
 
-       attrelation = heap_openr(AttributeRelationName);
        heap_replace(attrelation, &oldatttup->t_self, oldatttup, NULL);
 
        /* keep system catalog indices current */
@@ -159,7 +161,7 @@ renameatt(char *relname,
        CatalogCloseIndices(Num_pg_attr_indices, irelations);
 
        pfree(oldatttup);
-       heap_close(attrelation);
+       heap_close(attrelation, RowExclusiveLock);
 }
 
 /*
@@ -182,6 +184,7 @@ void
 renamerel(char *oldrelname, char *newrelname)
 {
        int                     i;
+       Relation        targetrelation;
        Relation        relrelation;    /* for RELATION relation */
        HeapTuple       oldreltup;
        char            oldpath[MAXPGPATH],
@@ -198,6 +201,15 @@ renamerel(char *oldrelname, char *newrelname)
                elog(ERROR, "renamerel: Illegal class name: \"%s\" -- pg_ is reserved for system catalogs",
                         newrelname);
 
+       /*
+        * Grab an exclusive lock on the target table, which we will NOT release
+        * until end of transaction.
+        */
+       targetrelation = heap_openr(oldrelname, AccessExclusiveLock);
+       heap_close(targetrelation, NoLock);     /* close rel but keep lock! */
+
+       relrelation = heap_openr(RelationRelationName, RowExclusiveLock);
+
        oldreltup = SearchSysCacheTupleCopy(RELNAME,
                                                                                PointerGetDatum(oldrelname),
                                                                                0, 0, 0);
@@ -207,12 +219,17 @@ renamerel(char *oldrelname, char *newrelname)
        if (RelnameFindRelid(newrelname) != InvalidOid)
                elog(ERROR, "renamerel: relation \"%s\" exists", newrelname);
 
+       /*
+        * XXX need to close relation and flush dirty buffers here!
+        */
+
        /* rename the path first, so if this fails the rename's not done */
        strcpy(oldpath, relpath(oldrelname));
        strcpy(newpath, relpath(newrelname));
        if (rename(oldpath, newpath) < 0)
                elog(ERROR, "renamerel: unable to rename file: %s", oldpath);
 
+       /* rename additional segments of relation, too */
        for (i = 1;; i++)
        {
                sprintf(toldpath, "%s.%d", oldpath, i);
@@ -225,7 +242,6 @@ renamerel(char *oldrelname, char *newrelname)
                        newrelname, NAMEDATALEN);
 
        /* insert fixed rel tuple */
-       relrelation = heap_openr(RelationRelationName);
        heap_replace(relrelation, &oldreltup->t_self, oldreltup, NULL);
 
        /* keep the system catalog indices current */
@@ -233,5 +249,5 @@ renamerel(char *oldrelname, char *newrelname)
        CatalogIndexInsert(irelations, Num_pg_class_indices, relrelation, oldreltup);
        CatalogCloseIndices(Num_pg_class_indices, irelations);
 
-       heap_close(relrelation);
+       heap_close(relrelation, RowExclusiveLock);
 }
index b7f959cd65eed7a01a76cde6c2093f5a17340640..be47d32f9f9abbbb9615aff038de5f0a4227a19c 100644 (file)
@@ -153,10 +153,7 @@ DefineSequence(CreateSeqStmt *seq)
 
        DefineRelation(stmt, RELKIND_SEQUENCE);
 
-       rel = heap_openr(seq->seqname);
-       Assert(RelationIsValid(rel));
-
-       LockRelation(rel, AccessExclusiveLock);
+       rel = heap_openr(seq->seqname, AccessExclusiveLock);
 
        tupDesc = RelationGetDescr(rel);
 
@@ -179,11 +176,7 @@ DefineSequence(CreateSeqStmt *seq)
        if (WriteBuffer(buf) == STATUS_ERROR)
                elog(ERROR, "DefineSequence: WriteBuffer failed");
 
-       UnlockRelation(rel, AccessExclusiveLock);
-       heap_close(rel);
-
-       return;
-
+       heap_close(rel, AccessExclusiveLock);
 }
 
 
@@ -422,12 +415,7 @@ init_sequence(char *caller, char *name)
                temp = elm;
        }
 
-       temp->rel = heap_openr(name);
-
-       if (!RelationIsValid(temp->rel))
-               elog(ERROR, "%s.%s: sequence does not exist", name, caller);
-
-       LockRelation(temp->rel, AccessShareLock);
+       temp->rel = heap_openr(name, AccessShareLock);
 
        if (temp->rel->rd_rel->relkind != RELKIND_SEQUENCE)
                elog(ERROR, "%s.%s: %s is not sequence !", name, caller, name);
@@ -453,7 +441,6 @@ init_sequence(char *caller, char *name)
        }
 
        return elm;
-
 }
 
 
@@ -467,20 +454,15 @@ CloseSequences(void)
        SeqTable        elm;
        Relation        rel;
 
-       for (elm = seqtab; elm != (SeqTable) NULL;)
+       for (elm = seqtab; elm != (SeqTable) NULL; elm = elm->next)
        {
                if (elm->rel != (Relation) NULL)                /* opened in current xact */
                {
                        rel = elm->rel;
                        elm->rel = (Relation) NULL;
-                       UnlockRelation(rel, AccessShareLock);
-                       heap_close(rel);
+                       heap_close(rel, AccessShareLock);
                }
-               elm = elm->next;
        }
-
-       return;
-
 }
 
 
index 55f67711c77514c2eae9fbe1713edcb982c66978..aa7a0b56c1d0988e2e208b384db0ba2e8599496b 100644 (file)
@@ -63,11 +63,7 @@ CreateTrigger(CreateTrigStmt *stmt)
                elog(ERROR, "%s: %s", stmt->relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
 #endif
 
-       rel = heap_openr(stmt->relname);
-       if (!RelationIsValid(rel))
-               elog(ERROR, "CreateTrigger: there is no relation %s", stmt->relname);
-
-       LockRelation(rel, AccessExclusiveLock);
+       rel = heap_openr(stmt->relname, AccessExclusiveLock);
 
        TRIGGER_CLEAR_TYPE(tgtype);
        if (stmt->before)
@@ -103,8 +99,7 @@ CreateTrigger(CreateTrigStmt *stmt)
        }
 
        /* Scan pg_trigger */
-       tgrel = heap_openr(TriggerRelationName);
-       LockRelation(tgrel, AccessExclusiveLock);
+       tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
        ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
                                                   F_OIDEQ, RelationGetRelid(rel));
        tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
@@ -203,20 +198,19 @@ CreateTrigger(CreateTrigStmt *stmt)
        CatalogIndexInsert(idescs, Num_pg_trigger_indices, tgrel, tuple);
        CatalogCloseIndices(Num_pg_trigger_indices, idescs);
        pfree(tuple);
-       UnlockRelation(tgrel, AccessExclusiveLock);
-       heap_close(tgrel);
+       heap_close(tgrel, RowExclusiveLock);
 
        pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1]));
        pfree(DatumGetPointer(values[Anum_pg_trigger_tgargs - 1]));
 
        /* update pg_class */
+       pgrel = heap_openr(RelationRelationName, RowExclusiveLock);
        tuple = SearchSysCacheTupleCopy(RELNAME,
                                                                        PointerGetDatum(stmt->relname),
                                                                        0, 0, 0);
        if (!HeapTupleIsValid(tuple))
                elog(ERROR, "CreateTrigger: relation %s not found in pg_class", stmt->relname);
 
-       pgrel = heap_openr(RelationRelationName);
        ((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1;
        RelationInvalidateHeapTuple(pgrel, tuple);
        heap_replace(pgrel, &tuple->t_self, tuple, NULL);
@@ -224,7 +218,7 @@ CreateTrigger(CreateTrigStmt *stmt)
        CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
        CatalogCloseIndices(Num_pg_class_indices, ridescs);
        pfree(tuple);
-       heap_close(pgrel);
+       heap_close(pgrel, RowExclusiveLock);
 
        CommandCounterIncrement();
        oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
@@ -232,8 +226,8 @@ CreateTrigger(CreateTrigStmt *stmt)
        rel->rd_rel->reltriggers = found + 1;
        RelationBuildTriggers(rel);
        MemoryContextSwitchTo(oldcxt);
-       heap_close(rel);
-       return;
+       /* Keep lock on target rel until end of xact */
+       heap_close(rel, NoLock);
 }
 
 void
@@ -255,14 +249,9 @@ DropTrigger(DropTrigStmt *stmt)
                elog(ERROR, "%s: %s", stmt->relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
 #endif
 
-       rel = heap_openr(stmt->relname);
-       if (!RelationIsValid(rel))
-               elog(ERROR, "DropTrigger: there is no relation %s", stmt->relname);
+       rel = heap_openr(stmt->relname, AccessExclusiveLock);
 
-       LockRelation(rel, AccessExclusiveLock);
-
-       tgrel = heap_openr(TriggerRelationName);
-       LockRelation(tgrel, AccessExclusiveLock);
+       tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
        ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
                                                   F_OIDEQ, RelationGetRelid(rel));
        tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
@@ -282,20 +271,19 @@ DropTrigger(DropTrigStmt *stmt)
                elog(ERROR, "DropTrigger: there is no trigger %s on relation %s",
                         stmt->trigname, stmt->relname);
        if (tgfound > 1)
-               elog(NOTICE, "DropTrigger: found (and deleted) %d trigger %s on relation %s",
+               elog(NOTICE, "DropTrigger: found (and deleted) %d triggers %s on relation %s",
                         tgfound, stmt->trigname, stmt->relname);
        heap_endscan(tgscan);
-       UnlockRelation(tgrel, AccessExclusiveLock);
-       heap_close(tgrel);
+       heap_close(tgrel, RowExclusiveLock);
 
+       /* update pg_class */
+       pgrel = heap_openr(RelationRelationName, RowExclusiveLock);
        tuple = SearchSysCacheTupleCopy(RELNAME,
                                                                        PointerGetDatum(stmt->relname),
                                                                        0, 0, 0);
        if (!HeapTupleIsValid(tuple))
                elog(ERROR, "DropTrigger: relation %s not found in pg_class", stmt->relname);
 
-       /* update pg_class */
-       pgrel = heap_openr(RelationRelationName);
        ((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found;
        RelationInvalidateHeapTuple(pgrel, tuple);
        heap_replace(pgrel, &tuple->t_self, tuple, NULL);
@@ -303,7 +291,7 @@ DropTrigger(DropTrigStmt *stmt)
        CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
        CatalogCloseIndices(Num_pg_class_indices, ridescs);
        pfree(tuple);
-       heap_close(pgrel);
+       heap_close(pgrel, RowExclusiveLock);
 
        CommandCounterIncrement();
        oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
@@ -312,8 +300,8 @@ DropTrigger(DropTrigStmt *stmt)
        if (found > 0)
                RelationBuildTriggers(rel);
        MemoryContextSwitchTo(oldcxt);
-       heap_close(rel);
-       return;
+       /* Keep lock on target rel until end of xact */
+       heap_close(rel, NoLock);
 }
 
 void
@@ -324,8 +312,7 @@ RelationRemoveTriggers(Relation rel)
        ScanKeyData key;
        HeapTuple       tup;
 
-       tgrel = heap_openr(TriggerRelationName);
-       LockRelation(tgrel, AccessExclusiveLock);
+       tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
        ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
                                                   F_OIDEQ, RelationGetRelid(rel));
 
@@ -335,9 +322,7 @@ RelationRemoveTriggers(Relation rel)
                heap_delete(tgrel, &tup->t_self, NULL);
 
        heap_endscan(tgscan);
-       UnlockRelation(tgrel, AccessExclusiveLock);
-       heap_close(tgrel);
-
+       heap_close(tgrel, RowExclusiveLock);
 }
 
 void
@@ -367,7 +352,7 @@ RelationBuildTriggers(Relation relation)
                                                   (RegProcedure) F_OIDEQ,
                                                   ObjectIdGetDatum(RelationGetRelid(relation)));
 
-       tgrel = heap_openr(TriggerRelationName);
+       tgrel = heap_openr(TriggerRelationName, AccessShareLock);
        irel = index_openr(TriggerRelidIndex);
        sd = index_beginscan(irel, false, 1, &skey);
 
@@ -441,7 +426,7 @@ RelationBuildTriggers(Relation relation)
        index_endscan(sd);
        pfree(sd);
        index_close(irel);
-       heap_close(tgrel);
+       heap_close(tgrel, AccessShareLock);
 
        /* Build trigdesc */
        trigdesc->triggers = triggers;
index 1b0d972839e40cab6a009758176807ae88590d5a..c05b6da58562893b1dfab6b31e1a436572141162 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: user.c,v 1.33 1999/07/30 18:09:47 momjian Exp $
+ * $Id: user.c,v 1.34 1999/09/18 19:06:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,13 +36,15 @@ static void CheckPgUserAclNotNull(void);
  *
  * copy the modified contents of pg_shadow to a file used by the postmaster
  * for user authentication.  The file is stored as $PGDATA/pg_pwd.
+ *
+ * NB: caller is responsible for ensuring that only one backend can
+ * execute this routine at a time.  Acquiring AccessExclusiveLock on
+ * pg_shadow is the standard way to do that.
  *---------------------------------------------------------------------
  */
-static
-void
+static void
 UpdatePgPwdFile(char *sql, CommandDest dest)
 {
-
        char       *filename,
                           *tempname;
        int                     bufsize;
@@ -125,17 +127,13 @@ DefineUser(CreateUserStmt *stmt, CommandDest dest)
 
        /*
         * Scan the pg_shadow relation to be certain the user doesn't already
-        * exist.
+        * exist.  Note we secure exclusive lock, because we also need to be
+        * sure of what the next usesysid should be, and we need to protect
+        * our update of the flat password file.
         */
-       pg_shadow_rel = heap_openr(ShadowRelationName);
+       pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock);
        pg_shadow_dsc = RelationGetDescr(pg_shadow_rel);
 
-       /*
-        * Secure a write lock on pg_shadow so we can be sure of what the next
-        * usesysid should be.
-        */
-       LockRelation(pg_shadow_rel, AccessExclusiveLock);
-
        scan = heap_beginscan(pg_shadow_rel, false, SnapshotNow, 0, NULL);
        while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
        {
@@ -152,8 +150,7 @@ DefineUser(CreateUserStmt *stmt, CommandDest dest)
 
        if (exists)
        {
-               UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
-               heap_close(pg_shadow_rel);
+               heap_close(pg_shadow_rel, AccessExclusiveLock);
                UserAbortTransactionBlock();
                elog(ERROR,
                 "defineUser: user \"%s\" has already been created", stmt->user);
@@ -165,6 +162,12 @@ DefineUser(CreateUserStmt *stmt, CommandDest dest)
         *
         * XXX Ugly as this code is, it still fails to cope with ' or \ in any of
         * the provided strings.
+        *
+        * XXX This routine would be *lots* better if it inserted the new
+        * tuple with formtuple/heap_insert.  For one thing, all of the
+        * transaction-block gamesmanship could be eliminated, because
+        * it's only there to make the world safe for a recursive call
+        * to pg_exec_query_dest().
         */
        snprintf(sql, SQL_LENGTH,
                         "insert into %s (usename,usesysid,usecreatedb,usetrace,"
@@ -189,17 +192,21 @@ DefineUser(CreateUserStmt *stmt, CommandDest dest)
        pg_exec_query_dest(sql, dest, false);
 
        /*
-        * Add the stuff here for groups.
+        * Add stuff here for groups?
         */
 
+       /*
+        * Write the updated pg_shadow data to the flat password file.
+        * Because we are still holding AccessExclusiveLock on pg_shadow,
+        * we can be sure no other backend will try to write the flat
+        * file at the same time.
+        */
        UpdatePgPwdFile(sql, dest);
 
        /*
-        * This goes after the UpdatePgPwdFile to be certain that two backends
-        * to not attempt to write to the pg_pwd file at the same time.
+        * Now we can clean up.
         */
-       UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
-       heap_close(pg_shadow_rel);
+       heap_close(pg_shadow_rel, AccessExclusiveLock);
 
        if (IsTransactionBlock() && !inblock)
                EndTransactionBlock();
@@ -237,70 +244,79 @@ AlterUser(AlterUserStmt *stmt, CommandDest dest)
 
        /*
         * Scan the pg_shadow relation to be certain the user exists.
+        * Note we secure exclusive lock to protect our update of the
+        * flat password file.
         */
-       pg_shadow_rel = heap_openr(ShadowRelationName);
+       pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock);
        pg_shadow_dsc = RelationGetDescr(pg_shadow_rel);
 
-       /*
-        * Secure a write lock on pg_shadow so we can be sure that when the
-        * dump of the pg_pwd file is done, there is not another backend doing
-        * the same.
-        */
-       LockRelation(pg_shadow_rel, AccessExclusiveLock);
-
        tuple = SearchSysCacheTuple(USENAME,
                                                                PointerGetDatum(stmt->user),
                                                                0, 0, 0);
        if (!HeapTupleIsValid(tuple))
        {
-               UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
-               heap_close(pg_shadow_rel);
-               UserAbortTransactionBlock();    /* needed? */
+               heap_close(pg_shadow_rel, AccessExclusiveLock);
+               UserAbortTransactionBlock();
                elog(ERROR, "alterUser: user \"%s\" does not exist", stmt->user);
-               return;
        }
 
        /*
         * Create the update statement to modify the user.
+        *
+        * XXX see diatribe in preceding routine.  This code is just as bogus.
         */
        snprintf(sql, SQL_LENGTH, "update %s set", ShadowRelationName);
 
        if (stmt->password)
-               snprintf(sql, SQL_LENGTH, "%s passwd = '%s'", pstrdup(sql), stmt->password);
+               snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql),
+                                " passwd = '%s'", stmt->password);
 
        if (stmt->createdb)
        {
-               snprintf(sql, SQL_LENGTH, "%s %susecreatedb='%s'",
-                                pstrdup(sql), stmt->password ? "," : "",
+               snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql),
+                                "%s usecreatedb='%s'",
+                                stmt->password ? "," : "",
                                 *stmt->createdb ? "t" : "f");
        }
 
        if (stmt->createuser)
        {
-               snprintf(sql, SQL_LENGTH, "%s %susesuper='%s'",
-                        pstrdup(sql), (stmt->password || stmt->createdb) ? "," : "",
+               snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql),
+                                "%s usesuper='%s'",
+                                (stmt->password || stmt->createdb) ? "," : "",
                                 *stmt->createuser ? "t" : "f");
        }
 
        if (stmt->validUntil)
        {
-               snprintf(sql, SQL_LENGTH, "%s %svaluntil='%s'",
-                                pstrdup(sql),
+               snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql),
+                                "%s valuntil='%s'",
                (stmt->password || stmt->createdb || stmt->createuser) ? "," : "",
                                 stmt->validUntil);
        }
 
-       snprintf(sql, SQL_LENGTH, "%s where usename = '%s'",
-                        pstrdup(sql), stmt->user);
+       snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql),
+                        " where usename = '%s'",
+                        stmt->user);
 
        pg_exec_query_dest(sql, dest, false);
 
-       /* do the pg_group stuff here */
+       /*
+        * Add stuff here for groups?
+        */
 
+       /*
+        * Write the updated pg_shadow data to the flat password file.
+        * Because we are still holding AccessExclusiveLock on pg_shadow,
+        * we can be sure no other backend will try to write the flat
+        * file at the same time.
+        */
        UpdatePgPwdFile(sql, dest);
 
-       UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
-       heap_close(pg_shadow_rel);
+       /*
+        * Now we can clean up.
+        */
+       heap_close(pg_shadow_rel, AccessExclusiveLock);
 
        if (IsTransactionBlock() && !inblock)
                EndTransactionBlock();
@@ -310,7 +326,6 @@ AlterUser(AlterUserStmt *stmt, CommandDest dest)
 extern void
 RemoveUser(char *user, CommandDest dest)
 {
-
        char       *pg_shadow;
        Relation        pg_shadow_rel,
                                pg_rel;
@@ -318,7 +333,7 @@ RemoveUser(char *user, CommandDest dest)
        HeapScanDesc scan;
        HeapTuple       tuple;
        Datum           datum;
-       char            sql[512];
+       char            sql[SQL_LENGTH];
        bool            n,
                                inblock;
        int32           usesysid;
@@ -341,27 +356,19 @@ RemoveUser(char *user, CommandDest dest)
        }
 
        /*
-        * Perform a scan of the pg_shadow relation to find the usesysid of
-        * the user to be deleted.      If it is not found, then return a warning
-        * message.
+        * Scan the pg_shadow relation to find the usesysid of the user to be
+        * deleted.  Note we secure exclusive lock, because we need to protect
+        * our update of the flat password file.
         */
-       pg_shadow_rel = heap_openr(ShadowRelationName);
+       pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock);
        pg_dsc = RelationGetDescr(pg_shadow_rel);
 
-       /*
-        * Secure a write lock on pg_shadow so we can be sure that when the
-        * dump of the pg_pwd file is done, there is not another backend doing
-        * the same.
-        */
-       LockRelation(pg_shadow_rel, AccessExclusiveLock);
-
        tuple = SearchSysCacheTuple(USENAME,
                                                                PointerGetDatum(user),
                                                                0, 0, 0);
        if (!HeapTupleIsValid(tuple))
        {
-               UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
-               heap_close(pg_shadow_rel);
+               heap_close(pg_shadow_rel, AccessExclusiveLock);
                UserAbortTransactionBlock();
                elog(ERROR, "removeUser: user \"%s\" does not exist", user);
        }
@@ -372,7 +379,7 @@ RemoveUser(char *user, CommandDest dest)
         * Perform a scan of the pg_database relation to find the databases
         * owned by usesysid.  Then drop them.
         */
-       pg_rel = heap_openr(DatabaseRelationName);
+       pg_rel = heap_openr(DatabaseRelationName, AccessExclusiveLock);
        pg_dsc = RelationGetDescr(pg_rel);
 
        scan = heap_beginscan(pg_rel, false, SnapshotNow, 0, NULL);
@@ -383,7 +390,7 @@ RemoveUser(char *user, CommandDest dest)
                if ((int) datum == usesysid)
                {
                        datum = heap_getattr(tuple, Anum_pg_database_datname, pg_dsc, &n);
-                       if (memcmp((void *) datum, "template1", 9))
+                       if (memcmp((void *) datum, "template1", 9) != 0)
                        {
                                dbase =
                                        (char **) repalloc((void *) dbase, sizeof(char *) * (ndbase + 1));
@@ -394,12 +401,12 @@ RemoveUser(char *user, CommandDest dest)
                }
        }
        heap_endscan(scan);
-       heap_close(pg_rel);
+       heap_close(pg_rel, AccessExclusiveLock);
 
        while (ndbase--)
        {
                elog(NOTICE, "Dropping database %s", dbase[ndbase]);
-               snprintf(sql, SQL_LENGTH, "drop database %s", dbase[ndbase]);
+               snprintf(sql, SQL_LENGTH, "DROP DATABASE %s", dbase[ndbase]);
                pfree((void *) dbase[ndbase]);
                pg_exec_query_dest(sql, dest, false);
        }
@@ -431,10 +438,18 @@ RemoveUser(char *user, CommandDest dest)
                "delete from %s where usename = '%s'", ShadowRelationName, user);
        pg_exec_query_dest(sql, dest, false);
 
+       /*
+        * Write the updated pg_shadow data to the flat password file.
+        * Because we are still holding AccessExclusiveLock on pg_shadow,
+        * we can be sure no other backend will try to write the flat
+        * file at the same time.
+        */
        UpdatePgPwdFile(sql, dest);
 
-       UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
-       heap_close(pg_shadow_rel);
+       /*
+        * Now we can clean up.
+        */
+       heap_close(pg_shadow_rel, AccessExclusiveLock);
 
        if (IsTransactionBlock() && !inblock)
                EndTransactionBlock();
index 55ec864fca5b02559e3f450ce4af72c51f899ed3..3027763b46861368eaf2f585795ec2b9440f185c 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.119 1999/08/25 12:20:57 ishii Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.120 1999/09/18 19:06:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -304,7 +304,7 @@ vc_getrels(NameData *VacRelP)
        portalmem = PortalGetVariableMemory(vc_portal);
        vrl = cur = (VRelList) NULL;
 
-       rel = heap_openr(RelationRelationName);
+       rel = heap_openr(RelationRelationName, AccessShareLock);
        tupdesc = RelationGetDescr(rel);
 
        scan = heap_beginscan(rel, false, SnapshotNow, 1, &key);
@@ -343,9 +343,8 @@ vc_getrels(NameData *VacRelP)
        if (found == false)
                elog(NOTICE, "Vacuum: table not found");
 
-
        heap_endscan(scan);
-       heap_close(rel);
+       heap_close(rel, AccessShareLock);
 
        CommitTransactionCommand();
 
@@ -395,8 +394,10 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
                return;
        }
 
-       /* now open the class and vacuum it */
-       onerel = heap_open(relid);
+       /*
+        * Open the class, get an exclusive lock on it, and vacuum it
+        */
+       onerel = heap_open(relid, AccessExclusiveLock);
 
        vacrelstats = (VRelStats *) palloc(sizeof(VRelStats));
        vacrelstats->relid = relid;
@@ -509,9 +510,6 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
                vacrelstats->vacattrstats = (VacAttrStats *) NULL;
        }
 
-       /* we require the relation to be locked until the indices are cleaned */
-       LockRelation(onerel, AccessExclusiveLock);
-
        GetXmaxRecent(&XmaxRecent);
 
        /* scan it */
@@ -565,13 +563,13 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
                        pfree(fraged_pages.vpl_pagedesc);
        }
 
-       /* all done with this class */
-       heap_close(onerel);
-
        /* update statistics in pg_class */
        vc_updstats(vacrelstats->relid, vacrelstats->num_pages,
                        vacrelstats->num_tuples, vacrelstats->hasindex, vacrelstats);
 
+       /* all done with this class, but hold lock until commit */
+       heap_close(onerel, NoLock);
+
        /* next command frees attribute stats */
        CommitTransactionCommand();
 }
@@ -2281,6 +2279,8 @@ vc_updstats(Oid relid, int num_pages, int num_tuples, bool hasindex, VRelStats *
        /*
         * update number of tuples and number of pages in pg_class
         */
+       rd = heap_openr(RelationRelationName, RowExclusiveLock);
+
        ctup = SearchSysCacheTupleCopy(RELOID,
                                                                   ObjectIdGetDatum(relid),
                                                                   0, 0, 0);
@@ -2288,8 +2288,6 @@ vc_updstats(Oid relid, int num_pages, int num_tuples, bool hasindex, VRelStats *
                elog(ERROR, "pg_class entry for relid %u vanished during vacuuming",
                         relid);
 
-       rd = heap_openr(RelationRelationName);
-
        /* get the buffer cache tuple */
        rtup.t_self = ctup->t_self;
        heap_fetch(rd, SnapshotNow, &rtup, &buffer);
@@ -2306,8 +2304,8 @@ vc_updstats(Oid relid, int num_pages, int num_tuples, bool hasindex, VRelStats *
                VacAttrStats *vacattrstats = vacrelstats->vacattrstats;
                int                     natts = vacrelstats->va_natts;
 
-               ad = heap_openr(AttributeRelationName);
-               sd = heap_openr(StatisticRelationName);
+               ad = heap_openr(AttributeRelationName, RowExclusiveLock);
+               sd = heap_openr(StatisticRelationName, RowExclusiveLock);
                ScanKeyEntryInitialize(&askey, 0, Anum_pg_attribute_attrelid,
                                                           F_INT4EQ, relid);
 
@@ -2458,8 +2456,8 @@ vc_updstats(Oid relid, int num_pages, int num_tuples, bool hasindex, VRelStats *
                        }
                }
                heap_endscan(scan);
-               heap_close(ad);
-               heap_close(sd);
+               heap_close(ad, RowExclusiveLock);
+               heap_close(sd, RowExclusiveLock);
        }
 
        /*
@@ -2469,7 +2467,7 @@ vc_updstats(Oid relid, int num_pages, int num_tuples, bool hasindex, VRelStats *
 
        WriteBuffer(buffer);
 
-       heap_close(rd);
+       heap_close(rd, RowExclusiveLock);
 }
 
 /*
@@ -2484,7 +2482,7 @@ vc_delhilowstats(Oid relid, int attcnt, int *attnums)
        HeapTuple       tuple;
        ScanKeyData key;
 
-       pgstatistic = heap_openr(StatisticRelationName);
+       pgstatistic = heap_openr(StatisticRelationName, RowExclusiveLock);
 
        if (relid != InvalidOid)
        {
@@ -2515,7 +2513,7 @@ vc_delhilowstats(Oid relid, int attcnt, int *attnums)
        }
 
        heap_endscan(scan);
-       heap_close(pgstatistic);
+       heap_close(pgstatistic, RowExclusiveLock);
 }
 
 /*
@@ -2721,7 +2719,7 @@ vc_getindices(Oid relid, int *nindices, Relation **Irel)
        ioid = (Oid *) palloc(10 * sizeof(Oid));
 
        /* prepare a heap scan on the pg_index relation */
-       pgindex = heap_openr(IndexRelationName);
+       pgindex = heap_openr(IndexRelationName, AccessShareLock);
        tupdesc = RelationGetDescr(pgindex);
 
        ScanKeyEntryInitialize(&key, 0x0, Anum_pg_index_indrelid,
@@ -2741,7 +2739,7 @@ vc_getindices(Oid relid, int *nindices, Relation **Irel)
        }
 
        heap_endscan(scan);
-       heap_close(pgindex);
+       heap_close(pgindex, AccessShareLock);
 
        if (i == 0)
        {                                                       /* No one index found */
index 40a94fd02c85021c143e85890be6a198a45be4be..9c1b7b8bb41ae19405de1579bd071c1764521f44 100644 (file)
@@ -1,11 +1,11 @@
 /*-------------------------------------------------------------------------
  *
  * execAmi.c
- *       miscellanious executor access method routines
+ *       miscellaneous executor access method routines
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- *     $Id: execAmi.c,v 1.41 1999/07/17 20:16:56 momjian Exp $
+ *     $Id: execAmi.c,v 1.42 1999/09/18 19:06:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -52,7 +52,6 @@
 
 static Pointer ExecBeginScan(Relation relation, int nkeys, ScanKey skeys,
                          bool isindex, ScanDirection dir, Snapshot snapshot);
-static Relation ExecOpenR(Oid relationOid, bool isindex);
 
 /* ----------------------------------------------------------------
  *             ExecOpenScanR
@@ -90,47 +89,33 @@ ExecOpenScanR(Oid relOid,
         *                abstraction someday -cim 9/9/89
         * ----------------
         */
-       relation = ExecOpenR(relOid, isindex);
-       scanDesc = ExecBeginScan(relation,
-                                                        nkeys,
-                                                        skeys,
-                                                        isindex,
-                                                        dir,
-                                                        snapshot);
-
-       if (returnRelation != NULL)
-               *returnRelation = relation;
-       if (scanDesc != NULL)
-               *returnScanDesc = scanDesc;
-}
-
-/* ----------------------------------------------------------------
- *             ExecOpenR
- *
- *             returns a relation descriptor given an object id.
- * ----------------------------------------------------------------
- */
-static Relation
-ExecOpenR(Oid relationOid, bool isindex)
-{
-       Relation        relation;
-
-       relation = (Relation) NULL;
 
        /* ----------------
         *      open the relation with the correct call depending
         *      on whether this is a heap relation or an index relation.
+        *
+        *      Do not lock the rel here; beginscan will acquire AccessShareLock.
         * ----------------
         */
        if (isindex)
-               relation = index_open(relationOid);
+               relation = index_open(relOid);
        else
-               relation = heap_open(relationOid);
+               relation = heap_open(relOid, NoLock);
 
        if (relation == NULL)
-               elog(DEBUG, "ExecOpenR: relation == NULL, heap_open failed.");
+               elog(ERROR, "ExecOpenScanR: failed to open relation %u", relOid);
+
+       scanDesc = ExecBeginScan(relation,
+                                                        nkeys,
+                                                        skeys,
+                                                        isindex,
+                                                        dir,
+                                                        snapshot);
 
-       return relation;
+       if (returnRelation != NULL)
+               *returnRelation = relation;
+       if (scanDesc != NULL)
+               *returnScanDesc = scanDesc;
 }
 
 /* ----------------------------------------------------------------
@@ -243,15 +228,20 @@ ExecCloseR(Plan *node)
        if (scanDesc != NULL)
                heap_endscan(scanDesc);
 
+       /*
+        * endscan released AccessShareLock acquired by beginscan.  If we are
+        * holding any stronger locks on the rel, they should be held till end of
+        * xact.  Therefore, we need only close the rel and not release locks.
+        */
        if (relation != NULL)
-               heap_close(relation);
+               heap_close(relation, NoLock);
 
        /* ----------------
         *      if this is an index scan then we have to take care
         *      of the index relations as well..
         * ----------------
         */
-       if (nodeTag(node) == T_IndexScan)
+       if (IsA(node, IndexScan))
        {
                IndexScan  *iscan = (IndexScan *) node;
                IndexScanState *indexstate;
index 48c0a885f3c27e1334ce8c47d3063c720935ce97..97dffe548f74577027a585331782d70d9ba4b1da 100644 (file)
@@ -26,7 +26,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.93 1999/07/17 20:16:57 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.94 1999/09/18 19:06:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -587,14 +587,12 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
                resultRelationIndex = resultRelation;
                rtentry = rt_fetch(resultRelationIndex, rangeTable);
                resultRelationOid = rtentry->relid;
-               resultRelationDesc = heap_open(resultRelationOid);
+               resultRelationDesc = heap_open(resultRelationOid, RowExclusiveLock);
 
                if (resultRelationDesc->rd_rel->relkind == RELKIND_SEQUENCE)
                        elog(ERROR, "You can't change sequence relation %s",
                                 resultRelationDesc->rd_rel->relname.data);
 
-               LockRelation(resultRelationDesc, RowExclusiveLock);
-
                resultRelationInfo = makeNode(RelationInfo);
                resultRelationInfo->ri_RangeTableIndex = resultRelationIndex;
                resultRelationInfo->ri_RelationDesc = resultRelationDesc;
@@ -636,8 +634,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
                {
                        rm = lfirst(l);
                        relid = ((RangeTblEntry *) nth(rm->rti - 1, rangeTable))->relid;
-                       relation = heap_open(relid);
-                       LockRelation(relation, RowShareLock);
+                       relation = heap_open(relid, RowShareLock);
                        if (!(rm->info & ROW_MARK_FOR_UPDATE))
                                continue;
                        erm = (execRowMark *) palloc(sizeof(execRowMark));
@@ -758,7 +755,8 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
                                 */
                                setheapoverride(true);
 
-                               intoRelationDesc = heap_open(intoRelationId);
+                               intoRelationDesc = heap_open(intoRelationId,
+                                                                                        AccessExclusiveLock);
 
                                setheapoverride(false);
                        }
@@ -809,14 +807,15 @@ EndPlan(Plan *plan, EState *estate)
        }
 
        /*
-        * close the result relations if necessary
+        * close the result relations if necessary,
+        * but hold locks on them until xact commit
         */
        if (resultRelationInfo != NULL)
        {
                Relation        resultRelationDesc;
 
                resultRelationDesc = resultRelationInfo->ri_RelationDesc;
-               heap_close(resultRelationDesc);
+               heap_close(resultRelationDesc, NoLock);
 
                /*
                 * close indices on the result relation
@@ -828,7 +827,7 @@ EndPlan(Plan *plan, EState *estate)
         * close the "into" relation if necessary
         */
        if (intoRelationDesc != NULL)
-               heap_close(intoRelationDesc);
+               heap_close(intoRelationDesc, NoLock);
 }
 
 /* ----------------------------------------------------------------
index 4bacf3f7bdbcc97980d138e49ed5245c631e8bcc..197995c346228efce0a8d30bc2ad71d0f02574a7 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.48 1999/07/16 04:58:47 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.49 1999/09/18 19:06:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -772,7 +772,7 @@ ExecOpenIndices(Oid resultRelationOid,
         *      open pg_index
         * ----------------
         */
-       indexRd = heap_openr(IndexRelationName);
+       indexRd = heap_openr(IndexRelationName, AccessShareLock);
 
        /* ----------------
         *      form a scan key
@@ -856,7 +856,7 @@ ExecOpenIndices(Oid resultRelationOid,
         * ----------------
         */
        heap_endscan(indexSd);
-       heap_close(indexRd);
+       heap_close(indexRd, AccessShareLock);
 
        /* ----------------
         *      Now that we've collected the index information into three
@@ -913,7 +913,7 @@ ExecOpenIndices(Oid resultRelationOid,
 
                                /*
                                 * Hack for not btree and hash indices: they use relation
-                                * level exclusive locking on updation (i.e. - they are
+                                * level exclusive locking on update (i.e. - they are
                                 * not ready for MVCC) and so we have to exclusively lock
                                 * indices here to prevent deadlocks if we will scan them
                                 * - index_beginscan places AccessShareLock, indices
@@ -1010,7 +1010,7 @@ ExecCloseIndices(RelationInfo *resultRelationInfo)
                        continue;
 
                /*
-                * Notes in ExecOpenIndices.
+                * See notes in ExecOpenIndices.
                 */
                if (relationDescs[i]->rd_rel->relam != BTREE_AM_OID &&
                        relationDescs[i]->rd_rel->relam != HASH_AM_OID)
index 19a1e53b69fef29d28ae407145306cf3a935a165..bd515d51f97af7525138f828934cc24abd28d7c8 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.24 1999/07/17 19:01:21 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.25 1999/09/18 19:06:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -257,7 +257,7 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
                        reloid = rtentry->relid;
                        rri = makeNode(RelationInfo);
                        rri->ri_RangeTableIndex = es_rri->ri_RangeTableIndex;
-                       rri->ri_RelationDesc = heap_open(reloid);
+                       rri->ri_RelationDesc = heap_open(reloid, RowExclusiveLock);
                        rri->ri_NumIndices = 0;
                        rri->ri_IndexRelationDescs = NULL;      /* index descs */
                        rri->ri_IndexRelationInfo = NULL;       /* index key info */
@@ -484,7 +484,7 @@ ExecEndAppend(Append *node)
 
                resultRelationInfo = (RelationInfo *) lfirst(resultRelationInfoList);
                resultRelationDesc = resultRelationInfo->ri_RelationDesc;
-               heap_close(resultRelationDesc);
+               heap_close(resultRelationDesc, NoLock);
                pfree(resultRelationInfo);
                resultRelationInfoList = lnext(resultRelationInfoList);
        }
index 68fb4eda07e7f7820363b6373c59757fe67237c6..3964d5d5bbe9d234f6b8682bac54194ba458d815 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.71 1999/09/13 00:17:19 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.72 1999/09/18 19:06:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1163,7 +1163,7 @@ clause_pred_clause_test(Expr *predicate, Node *clause)
                                                   F_OIDEQ,
                                                   ObjectIdGetDatum(pred_op));
 
-       relation = heap_openr(AccessMethodOperatorRelationName);
+       relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock);
 
        /*
         * The following assumes that any given operator will only be in a
@@ -1178,6 +1178,8 @@ clause_pred_clause_test(Expr *predicate, Node *clause)
        if (!HeapTupleIsValid(tuple))
        {
                elog(DEBUG, "clause_pred_clause_test: unknown pred_op");
+               heap_endscan(scan);
+               heap_close(relation, AccessShareLock);
                return false;
        }
        aform = (Form_pg_amop) GETSTRUCT(tuple);
@@ -1209,6 +1211,8 @@ clause_pred_clause_test(Expr *predicate, Node *clause)
        if (!HeapTupleIsValid(tuple))
        {
                elog(DEBUG, "clause_pred_clause_test: unknown clause_op");
+               heap_endscan(scan);
+               heap_close(relation, AccessShareLock);
                return false;
        }
        aform = (Form_pg_amop) GETSTRUCT(tuple);
@@ -1224,8 +1228,10 @@ clause_pred_clause_test(Expr *predicate, Node *clause)
 
        test_strategy = BT_implic_table[clause_strategy - 1][pred_strategy - 1];
        if (test_strategy == 0)
+       {
+               heap_close(relation, AccessShareLock);
                return false;                   /* the implication cannot be determined */
-
+       }
 
        /*
         * 4. From the same opclass, find the operator for the test strategy
@@ -1241,14 +1247,18 @@ clause_pred_clause_test(Expr *predicate, Node *clause)
        if (!HeapTupleIsValid(tuple))
        {
                elog(DEBUG, "clause_pred_clause_test: unknown test_op");
+               heap_endscan(scan);
+               heap_close(relation, AccessShareLock);
                return false;
        }
        aform = (Form_pg_amop) GETSTRUCT(tuple);
 
        /* Get the test operator */
        test_op = aform->amopopr;
+
        heap_endscan(scan);
 
+       heap_close(relation, AccessShareLock);
 
        /*
         * 5. Evaluate the test
index a22d3ed43ae8bbe247f1dc505f3073e067529b71..32a5bb52cda04e18c8e18205e259150b19e2d69c 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.67 1999/09/13 00:17:25 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.68 1999/09/18 19:07:00 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -627,7 +627,6 @@ pg_checkretval(Oid rettype, List *queryTreeList)
        Resdom     *resnode;
        Relation        reln;
        Oid                     relid;
-       Oid                     tletype;
        int                     relnatts;
        int                     i;
 
@@ -713,11 +712,7 @@ pg_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));
-
-       if (!RelationIsValid(reln))
-               elog(ERROR, "cannot open relation relid %u", typeTypeRelid(typ));
-
+       reln = heap_open(typeTypeRelid(typ), AccessShareLock);
        relid = reln->rd_id;
        relnatts = reln->rd_rel->relnatts;
 
@@ -729,41 +724,12 @@ pg_checkretval(Oid rettype, List *queryTreeList)
        {
                TargetEntry *tle = lfirst(tlist);
                Node       *thenode = tle->expr;
+               Oid                     tletype = exprType(thenode);
 
-               tlist = lnext(tlist);
-               tletype = exprType(thenode);
-
-#ifdef NOT_USED                                        /* fix me */
-               /* this is tedious */
-               if (IsA(thenode, Var))
-                       tletype = (Oid) ((Var *) thenode)->vartype;
-               else if (IsA(thenode, Const))
-                       tletype = (Oid) ((Const *) thenode)->consttype;
-               else if (IsA(thenode, Param))
-                       tletype = (Oid) ((Param *) thenode)->paramtype;
-               else if (IsA(thenode, Expr))
-                       tletype = Expr;
-
-               else if (IsA(thenode, LispList))
-               {
-                       thenode = lfirst(thenode);
-                       if (IsA(thenode, Oper))
-                               tletype = (Oid) get_opresulttype((Oper *) thenode);
-                       else if (IsA(thenode, Func))
-                               tletype = (Oid) get_functype((Func *) thenode);
-                       else
-                               elog(ERROR, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ));
-               }
-               else
-                       elog(ERROR, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ));
-#endif
-               /* reach right in there, why don't you? */
                if (tletype != reln->rd_att->attrs[i - 1]->atttypid)
                        elog(ERROR, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ));
+               tlist = lnext(tlist);
        }
 
-       heap_close(reln);
-
-       /* success */
-       return;
+       heap_close(reln, AccessShareLock);
 }
index 9ca188bce62d42e8c7c8ac60a50400fdeaf71cd0..ef120f8d2fe513df543ac5203102e955391ac782 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.37 1999/09/09 02:35:53 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.38 1999/09/18 19:07:06 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -126,17 +126,19 @@ index_info(Query *root, bool first, int relid, IdxInfoRetval *info)
        /* Find an index on the given relation */
        if (first)
        {
-               if (RelationIsValid(relation))
-                       heap_close(relation);
                if (HeapScanIsValid(scan))
                        heap_endscan(scan);
+               scan = (HeapScanDesc) NULL;
+               if (RelationIsValid(relation))
+                       heap_close(relation, AccessShareLock);
+               relation = (Relation) NULL;
 
                ScanKeyEntryInitialize(&indexKey, 0,
                                                           Anum_pg_index_indrelid,
                                                           F_OIDEQ,
                                                           ObjectIdGetDatum(indrelid));
 
-               relation = heap_openr(IndexRelationName);
+               relation = heap_openr(IndexRelationName, AccessShareLock);
                scan = heap_beginscan(relation, 0, SnapshotNow,
                                                          1, &indexKey);
        }
@@ -146,7 +148,7 @@ index_info(Query *root, bool first, int relid, IdxInfoRetval *info)
        if (!HeapTupleIsValid(indexTuple))
        {
                heap_endscan(scan);
-               heap_close(relation);
+               heap_close(relation, AccessShareLock);
                scan = (HeapScanDesc) NULL;
                relation = (Relation) NULL;
                return 0;
@@ -190,7 +192,7 @@ index_info(Query *root, bool first, int relid, IdxInfoRetval *info)
        info->relam = relam;
        info->pages = indexRelation->rd_rel->relpages;
        info->tuples = indexRelation->rd_rel->reltuples;
-       heap_close(indexRelation);
+       index_close(indexRelation);
 
        /*
         * Find the index ordering keys
@@ -390,7 +392,7 @@ find_inheritance_children(Oid inhparent)
        key[0].sk_nargs = key[0].sk_func.fn_nargs;
 
        key[0].sk_argument = ObjectIdGetDatum((Oid) inhparent);
-       relation = heap_openr(InheritsRelationName);
+       relation = heap_openr(InheritsRelationName, AccessShareLock);
        scan = heap_beginscan(relation, 0, SnapshotNow, 1, key);
        while (HeapTupleIsValid(inheritsTuple = heap_getnext(scan, 0)))
        {
@@ -398,7 +400,7 @@ find_inheritance_children(Oid inhparent)
                list = lappendi(list, inhrelid);
        }
        heap_endscan(scan);
-       heap_close(relation);
+       heap_close(relation, AccessShareLock);
        return list;
 }
 
@@ -424,8 +426,8 @@ VersionGetParents(Oid verrelid)
 
        fmgr_info(F_OIDEQ, &key[0].sk_func);
        key[0].sk_nargs = key[0].sk_func.fn_nargs;
-       relation = heap_openr(VersionRelationName);
        key[0].sk_argument = ObjectIdGetDatum(verrelid);
+       relation = heap_openr(VersionRelationName, AccessShareLock);
        scan = heap_beginscan(relation, 0, SnapshotNow, 1, key);
        while (HeapTupleIsValid(versionTuple = heap_getnext(scan, 0)))
        {
@@ -438,7 +440,7 @@ VersionGetParents(Oid verrelid)
                heap_rescan(scan, 0, key);
        }
        heap_endscan(scan);
-       heap_close(relation);
+       heap_close(relation, AccessShareLock);
        return list;
 }
 
index 2c4d1c7a7e824fc8535bee0a86f1db8825652a09..276d28b3aa14e9474e887af207190ff0dac9daa8 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- *     $Id: analyze.c,v 1.118 1999/08/21 03:48:55 tgl Exp $
+ *     $Id: analyze.c,v 1.119 1999/09/18 19:07:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -64,7 +64,7 @@ parse_analyze(List *pl, ParseState *parentParseState)
 
                parsetree = transformStmt(pstate, lfirst(pl));
                if (pstate->p_target_relation != NULL)
-                       heap_close(pstate->p_target_relation);
+                       heap_close(pstate->p_target_relation, AccessShareLock);
                pstate->p_target_relation = NULL;
                pstate->p_target_rangetblentry = NULL;
 
@@ -73,7 +73,7 @@ parse_analyze(List *pl, ParseState *parentParseState)
                        result = lappend(result,
                                                         transformStmt(pstate, lfirst(extras_before)));
                        if (pstate->p_target_relation != NULL)
-                               heap_close(pstate->p_target_relation);
+                               heap_close(pstate->p_target_relation, AccessShareLock);
                        pstate->p_target_relation = NULL;
                        pstate->p_target_rangetblentry = NULL;
                        extras_before = lnext(extras_before);
@@ -86,7 +86,7 @@ parse_analyze(List *pl, ParseState *parentParseState)
                        result = lappend(result,
                                                         transformStmt(pstate, lfirst(extras_after)));
                        if (pstate->p_target_relation != NULL)
-                               heap_close(pstate->p_target_relation);
+                               heap_close(pstate->p_target_relation, AccessShareLock);
                        pstate->p_target_relation = NULL;
                        pstate->p_target_rangetblentry = NULL;
                        extras_after = lnext(extras_after);
index 234987fb5f0472ba7ea3e545575b251169dc2e5d..bae53ebbd875e1761b4fff0aa5201dc74ef3001b 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.44 1999/08/21 03:48:55 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.45 1999/09/18 19:07:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -75,11 +75,11 @@ setTargetTable(ParseState *pstate, char *relname)
 
        /* This could only happen for multi-action rules */
        if (pstate->p_target_relation != NULL)
-               heap_close(pstate->p_target_relation);
+               heap_close(pstate->p_target_relation, AccessShareLock);
 
        pstate->p_target_rangetblentry = rte;
-       pstate->p_target_relation = heap_open(rte->relid);
-       /* will close relation later */
+       pstate->p_target_relation = heap_open(rte->relid, AccessShareLock);
+       /* will close relation later, see analyze.c */
 }
 
 /*
index 19a287d99e882fb5bb7637cbadb0ab83a09c7295..15e63f7c98fa461995a65224aac5d3f91fa7bfd5 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.54 1999/08/22 20:15:03 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.55 1999/09/18 19:07:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -139,7 +139,7 @@ agg_get_candidates(char *aggname,
        fmgr_info(F_NAMEEQ, (FmgrInfo *) &aggKey[0].sk_func);
        aggKey[0].sk_argument = NameGetDatum(aggname);
 
-       pg_aggregate_desc = heap_openr(AggregateRelationName);
+       pg_aggregate_desc = heap_openr(AggregateRelationName, AccessShareLock);
        pg_aggregate_scan = heap_beginscan(pg_aggregate_desc,
                                                                           0,
                                                                           SnapshotSelf,        /* ??? */
@@ -159,7 +159,7 @@ agg_get_candidates(char *aggname,
        }
 
        heap_endscan(pg_aggregate_scan);
-       heap_close(pg_aggregate_desc);
+       heap_close(pg_aggregate_desc, AccessShareLock);
 
        return ncandidates;
 }      /* agg_get_candidates() */
@@ -310,11 +310,11 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
                        if (attisset)
                        {
                                toid = exprType(first_arg);
-                               rd = heap_openr(typeidTypeName(toid));
+                               rd = heap_openr(typeidTypeName(toid), NoLock);
                                if (RelationIsValid(rd))
                                {
                                        relname = RelationGetRelationName(rd)->data;
-                                       heap_close(rd);
+                                       heap_close(rd, NoLock);
                                }
                                else
                                        elog(ERROR, "Type '%s' is not a relation type",
@@ -646,7 +646,7 @@ func_get_candidates(char *funcname, int nargs)
        CandidateList current_candidate;
        int                     i;
 
-       heapRelation = heap_openr(ProcedureRelationName);
+       heapRelation = heap_openr(ProcedureRelationName, AccessShareLock);
        ScanKeyEntryInitialize(&skey,
                                                   (bits16) 0x0,
                                                   (AttrNumber) 1,
@@ -690,7 +690,7 @@ func_get_candidates(char *funcname, int nargs)
 
        index_endscan(sd);
        index_close(idesc);
-       heap_close(heapRelation);
+       heap_close(heapRelation, AccessShareLock);
 
        return candidates;
 }
@@ -1086,7 +1086,7 @@ find_inheritors(Oid relid, Oid **supervec)
        visited = DLNewList();
 
 
-       inhrel = heap_openr(InheritsRelationName);
+       inhrel = heap_openr(InheritsRelationName, AccessShareLock);
        inhtupdesc = RelationGetDescr(inhrel);
 
        /*
@@ -1140,12 +1140,12 @@ find_inheritors(Oid relid, Oid **supervec)
 
                if (qentry != (SuperQE *) NULL)
                {
-
                        /* save the type id, rather than the relation id */
-                       if ((rd = heap_open(qentry->sqe_relid)) == (Relation) NULL)
+                       rd = heap_open(qentry->sqe_relid, NoLock);
+                       if (! RelationIsValid(rd))
                                elog(ERROR, "Relid %u does not exist", qentry->sqe_relid);
                        qentry->sqe_relid = typeTypeId(typenameType(RelationGetRelationName(rd)->data));
-                       heap_close(rd);
+                       heap_close(rd, NoLock);
 
                        DLAddTail(visited, qe);
 
@@ -1153,7 +1153,7 @@ find_inheritors(Oid relid, Oid **supervec)
                }
        } while (qentry != (SuperQE *) NULL);
 
-       heap_close(inhrel);
+       heap_close(inhrel, AccessShareLock);
 
        if (nvisited > 0)
        {
@@ -1370,16 +1370,13 @@ ParseComplexProjection(ParseState *pstate,
                                         */
 
                                        /* add a tlist to the func node and return the Iter */
-                                       rd = heap_openr(typeidTypeName(argtype));
+                                       rd = heap_openr(typeidTypeName(argtype), NoLock);
                                        if (RelationIsValid(rd))
                                        {
                                                relid = RelationGetRelid(rd);
-                                               heap_close(rd);
-                                       }
-                                       if (RelationIsValid(rd))
-                                       {
                                                func->func_tlist = setup_tlist(funcname, argrelid);
                                                iter->itertype = attnumTypeId(rd, attnum);
+                                               heap_close(rd, NoLock);
                                                return (Node *) iter;
                                        }
                                        else
@@ -1427,16 +1424,12 @@ ParseComplexProjection(ParseState *pstate,
                                {
 
                                        /* add a tlist to the func node */
-                                       rd = heap_openr(typeidTypeName(argtype));
-                                       if (RelationIsValid(rd))
-                                       {
-                                               relid = RelationGetRelid(rd);
-                                               heap_close(rd);
-                                       }
+                                       rd = heap_openr(typeidTypeName(argtype), NoLock);
                                        if (RelationIsValid(rd))
                                        {
                                                Expr       *newexpr;
 
+                                               relid = RelationGetRelid(rd);
                                                funcnode->func_tlist = setup_tlist(funcname, argrelid);
                                                funcnode->functype = attnumTypeId(rd, attnum);
 
@@ -1446,8 +1439,11 @@ ParseComplexProjection(ParseState *pstate,
                                                newexpr->oper = (Node *) funcnode;
                                                newexpr->args = expr->args;
 
+                                               heap_close(rd, NoLock);
+
                                                return (Node *) newexpr;
                                        }
+                                       /* XXX why not an error condition if it's not there? */
 
                                }
 
@@ -1461,18 +1457,19 @@ ParseComplexProjection(ParseState *pstate,
                                 * If the Param is a complex type, this could be a
                                 * projection
                                 */
-                               rd = heap_openr(typeidTypeName(param->paramtype));
+                               rd = heap_openr(typeidTypeName(param->paramtype), NoLock);
                                if (RelationIsValid(rd))
                                {
                                        relid = RelationGetRelid(rd);
-                                       heap_close(rd);
                                        if ((attnum = get_attnum(relid, funcname))
                                                != InvalidAttrNumber)
                                        {
                                                param->paramtype = attnumTypeId(rd, attnum);
                                                param->param_tlist = setup_tlist(funcname, relid);
+                                               heap_close(rd, NoLock);
                                                return (Node *) param;
                                        }
+                                       heap_close(rd, NoLock);
                                }
                                break;
                        }
index 8f82e58517d748728586d18cc61278eac4a98b9e..5a5c8709969b36bce1b016157ad78f5379229ae4 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.31 1999/08/26 04:59:15 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.32 1999/09/18 19:07:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -75,7 +75,6 @@ binary_oper_get_candidates(char *opname,
        HeapScanDesc pg_operator_scan;
        HeapTuple       tup;
        Form_pg_operator oper;
-       int                     nkeys;
        int                     ncandidates = 0;
        ScanKeyData opKey[3];
 
@@ -91,13 +90,11 @@ binary_oper_get_candidates(char *opname,
                                                   F_CHAREQ,
                                                   CharGetDatum('b'));
 
-       nkeys = 2;
-
-       pg_operator_desc = heap_openr(OperatorRelationName);
+       pg_operator_desc = heap_openr(OperatorRelationName, AccessShareLock);
        pg_operator_scan = heap_beginscan(pg_operator_desc,
                                                                          0,
                                                                          SnapshotSelf,         /* ??? */
-                                                                         nkeys,
+                                                                         2,
                                                                          opKey);
 
        while (HeapTupleIsValid(tup = heap_getnext(pg_operator_scan, 0)))
@@ -114,7 +111,7 @@ binary_oper_get_candidates(char *opname,
        }
 
        heap_endscan(pg_operator_scan);
-       heap_close(pg_operator_desc);
+       heap_close(pg_operator_desc, AccessShareLock);
 
        return ncandidates;
 }      /* binary_oper_get_candidates() */
@@ -522,7 +519,7 @@ unary_oper_get_candidates(char *op,
        fmgr_info(F_CHAREQ, (FmgrInfo *) &opKey[1].sk_func);
        opKey[1].sk_argument = CharGetDatum(rightleft);
 
-       pg_operator_desc = heap_openr(OperatorRelationName);
+       pg_operator_desc = heap_openr(OperatorRelationName, AccessShareLock);
        pg_operator_scan = heap_beginscan(pg_operator_desc,
                                                                          0,
                                                                          SnapshotSelf,         /* ??? */
@@ -545,7 +542,7 @@ unary_oper_get_candidates(char *op,
        }
 
        heap_endscan(pg_operator_scan);
-       heap_close(pg_operator_desc);
+       heap_close(pg_operator_desc, AccessShareLock);
 
        return ncandidates;
 }      /* unary_oper_get_candidates() */
index 79b08635f0273ada348dedccc34bfc1d798c0480..af18087aa58db82b41e690aed4f77beff19b8600 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.26 1999/07/19 00:26:20 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.27 1999/09/18 19:07:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -202,14 +202,9 @@ addRangeTableEntry(ParseState *pstate,
        rte->relname = pstrdup(relname);
        rte->refname = pstrdup(refname);
 
-       relation = heap_openr(relname);
-       if (relation == NULL)
-               elog(ERROR, "%s: %s",
-                        relname, aclcheck_error_strings[ACLCHECK_NO_CLASS]);
-
+       relation = heap_openr(relname, AccessShareLock);
        rte->relid = RelationGetRelid(relation);
-
-       heap_close(relation);
+       heap_close(relation, AccessShareLock);
 
        /*
         * Flags - zero or more from inheritance,union,version or recursive
@@ -246,10 +241,7 @@ expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
        if (rte == NULL)
                rte = addRangeTableEntry(pstate, relname, refname, FALSE, FALSE);
 
-       rel = heap_open(rte->relid);
-       if (rel == NULL)
-               elog(ERROR, "Unable to expand all -- heap_open failed on %s",
-                        rte->refname);
+       rel = heap_open(rte->relid, AccessShareLock);
 
        maxattrs = RelationGetNumberOfAttributes(rel);
 
@@ -278,7 +270,7 @@ expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
                te_list = lappend(te_list, te);
        }
 
-       heap_close(rel);
+       heap_close(rel, AccessShareLock);
 
        return te_list;
 }
index c478a7facee76ce525d9f5c335d3d74927405730..ef96b85210c48c36d3d69166d25559babbfcaee8 100644 (file)
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.21 1999/07/16 04:59:39 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.22 1999/09/18 19:07:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -184,7 +184,7 @@ checkLockPerms(List *locks, Query *parsetree, int rt_index)
         * Get the usename of the rules event relation owner
         */
        rte = (RangeTblEntry *) nth(rt_index - 1, parsetree->rtable);
-       ev_rel = heap_openr(rte->relname);
+       ev_rel = heap_openr(rte->relname, AccessShareLock);
        usertup = SearchSysCacheTuple(USESYSID,
                                                          ObjectIdGetDatum(ev_rel->rd_rel->relowner),
                                                                  0, 0, 0);
@@ -193,7 +193,7 @@ checkLockPerms(List *locks, Query *parsetree, int rt_index)
                elog(ERROR, "cache lookup for userid %d failed",
                         ev_rel->rd_rel->relowner);
        }
-       heap_close(ev_rel);
+       heap_close(ev_rel, AccessShareLock);
        evowner = nameout(&(((Form_pg_shadow) GETSTRUCT(usertup))->usename));
 
        /*
index b118bf8de5dc7bda56100dd7fcf94141c4b46dd0..c9be17151a900c04390f4b22751bc48964228cd6 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.35 1999/07/19 07:07:21 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.36 1999/09/18 19:07:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -78,9 +78,7 @@ InsertRule(char *rulname,
        extern void eval_as_new_xact();
        char       *template;
 
-       eventrel = heap_openr(evobj);
-       if (eventrel == NULL)
-               elog(ERROR, "rules cannot be defined on relations not in schema");
+       eventrel = heap_openr(evobj, AccessShareLock);
        eventrel_oid = RelationGetRelid(eventrel);
 
        /*
@@ -90,7 +88,7 @@ InsertRule(char *rulname,
                evslot_index = -1;
        else
                evslot_index = attnameAttNum(eventrel, (char *) evslot);
-       heap_close(eventrel);
+       heap_close(eventrel, AccessShareLock);
 
        if (evinstead)
                is_instead = "t";
@@ -258,9 +256,7 @@ DefineQueryRewrite(RuleStmt *stmt)
                 * ... the targetlist of the SELECT action must exactly match the
                 * event relation, ...
                 */
-               event_relation = heap_openr(event_obj->relname);
-               if (event_relation == NULL)
-                       elog(ERROR, "virtual relations not supported yet");
+               event_relation = heap_openr(event_obj->relname, AccessShareLock);
 
                if (event_relation->rd_att->natts != length(query->targetList))
                        elog(ERROR, "select rules target list must match event relations structure");
@@ -297,7 +293,7 @@ DefineQueryRewrite(RuleStmt *stmt)
                        }
                }
 
-               heap_close(event_relation);
+               heap_close(event_relation, AccessShareLock);
 
                /*
                 * LIMIT in view is not supported
@@ -332,9 +328,7 @@ DefineQueryRewrite(RuleStmt *stmt)
         * This rule is allowed - install it.
         */
 
-       event_relation = heap_openr(event_obj->relname);
-       if (event_relation == NULL)
-               elog(ERROR, "virtual relations not supported yet");
+       event_relation = heap_openr(event_obj->relname, AccessShareLock);
        ev_relid = RelationGetRelid(event_relation);
 
        if (eslot_string == NULL)
@@ -347,7 +341,7 @@ DefineQueryRewrite(RuleStmt *stmt)
                event_attno = attnameAttNum(event_relation, eslot_string);
                event_attype = attnumTypeId(event_relation, event_attno);
        }
-       heap_close(event_relation);
+       heap_close(event_relation, AccessShareLock);
 
        /* fix bug about instead nothing */
        ValidateRule(event_type, event_obj->relname,
index 0fa7fd72d43681bfef5a290d7f857c40f8577ab8..b13cb5e3ed1cd5db2f142db51cf15e8aa1681bb0 100644 (file)
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.55 1999/08/25 23:21:43 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.56 1999/09/18 19:07:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2059,10 +2059,10 @@ fireRIRrules(Query *parsetree)
                        continue;
                }
 
-               rel = heap_openr(rte->relname);
+               rel = heap_openr(rte->relname, AccessShareLock);
                if (rel->rd_rules == NULL)
                {
-                       heap_close(rel);
+                       heap_close(rel, AccessShareLock);
                        continue;
                }
 
@@ -2112,7 +2112,7 @@ fireRIRrules(Query *parsetree)
                                                          &modified);
                }
 
-               heap_close(rel);
+               heap_close(rel, AccessShareLock);
        }
 
        fireRIRonSubselect((Node *) parsetree);
@@ -2452,9 +2452,9 @@ RewriteQuery(Query *parsetree, bool *instead_flag, List **qual_products)
         * the statement is an update, insert or delete - fire rules on it.
         */
        rt_entry = rt_fetch(result_relation, parsetree->rtable);
-       rt_entry_relation = heap_openr(rt_entry->relname);
+       rt_entry_relation = heap_openr(rt_entry->relname, AccessShareLock);
        rt_entry_locks = rt_entry_relation->rd_rules;
-       heap_close(rt_entry_relation);
+       heap_close(rt_entry_relation, AccessShareLock);
 
        if (rt_entry_locks != NULL)
        {
@@ -2469,7 +2469,6 @@ RewriteQuery(Query *parsetree, bool *instead_flag, List **qual_products)
        }
 
        return product_queries;
-
 }
 
 
@@ -2585,7 +2584,7 @@ RewritePreprocessQuery(Query *parsetree)
 
                rte = (RangeTblEntry *) nth(parsetree->resultRelation - 1,
                                                                        parsetree->rtable);
-               rd = heap_openr(rte->relname);
+               rd = heap_openr(rte->relname, AccessShareLock);
 
                foreach(tl, parsetree->targetList)
                {
@@ -2597,7 +2596,7 @@ RewritePreprocessQuery(Query *parsetree)
                                tle->resdom->resno = 0;
                }
 
-               heap_close(rd);
+               heap_close(rd, AccessShareLock);
        }
 }
 
index 14ceeead8486e5068ad685fda9b74f171da0a6ad..50e6c62c027beac0af47d36a97574e7bcfeb955f 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.28 1999/07/17 20:17:39 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.29 1999/09/18 19:07:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -76,7 +76,7 @@ RemoveRewriteRule(char *ruleName)
        /*
         * Open the pg_rewrite relation.
         */
-       RewriteRelation = heap_openr(RewriteRelationName);
+       RewriteRelation = heap_openr(RewriteRelationName, RowExclusiveLock);
 
        /*
         * Scan the RuleRelation ('pg_rewrite') until we find a tuple
@@ -90,7 +90,7 @@ RemoveRewriteRule(char *ruleName)
         */
        if (!HeapTupleIsValid(tuple))
        {
-               heap_close(RewriteRelation);
+               heap_close(RewriteRelation, RowExclusiveLock);
                elog(ERROR, "Rule '%s' not found\n", ruleName);
        }
 
@@ -125,7 +125,7 @@ RemoveRewriteRule(char *ruleName)
        heap_delete(RewriteRelation, &tuple->t_self, NULL);
 
        pfree(tuple);
-       heap_close(RewriteRelation);
+       heap_close(RewriteRelation, RowExclusiveLock);
 }
 
 /*
@@ -144,7 +144,7 @@ RelationRemoveRules(Oid relid)
        /*
         * Open the pg_rewrite relation.
         */
-       RewriteRelation = heap_openr(RewriteRelationName);
+       RewriteRelation = heap_openr(RewriteRelationName, RowExclusiveLock);
 
        /*
         * Scan the RuleRelation ('pg_rewrite') for all the tuples that has
@@ -162,5 +162,5 @@ RelationRemoveRules(Oid relid)
                heap_delete(RewriteRelation, &tuple->t_self, NULL);
 
        heap_endscan(scanDesc);
-       heap_close(RewriteRelation);
+       heap_close(RewriteRelation, RowExclusiveLock);
 }
index c8d9d023efed6c0d014594b054d4f3529ed9f89c..c089be56d31c55dfa8c38182abc86373c8d2921f 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.36 1999/07/16 04:59:41 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.37 1999/09/18 19:07:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -40,7 +40,7 @@ RuleIdGetActionInfo(Oid ruleoid, bool *instead_flag, Query **parseTrees)
        char       *rule_evqual_string = NULL;
        Node       *rule_evqual = NULL;
 
-       ruleRelation = heap_openr(RewriteRelationName);
+       ruleRelation = heap_openr(RewriteRelationName, AccessShareLock);
        ruleTupdesc = RelationGetDescr(ruleRelation);
        ruletuple = SearchSysCacheTuple(RULOID,
                                                                        ObjectIdGetDatum(ruleoid),
@@ -68,7 +68,7 @@ RuleIdGetActionInfo(Oid ruleoid, bool *instead_flag, Query **parseTrees)
        ruleparse = (Query *) stringToNode(ruleaction);
        rule_evqual = (Node *) stringToNode(rule_evqual_string);
 
-       heap_close(ruleRelation);
+       heap_close(ruleRelation, AccessShareLock);
 
        *parseTrees = ruleparse;
        return rule_evqual;
@@ -79,23 +79,11 @@ RuleIdGetActionInfo(Oid ruleoid, bool *instead_flag, Query **parseTrees)
 int
 IsDefinedRewriteRule(char *ruleName)
 {
-       Relation        RewriteRelation = NULL;
        HeapTuple       tuple;
 
-
-       /*
-        * Open the pg_rewrite relation.
-        */
-       RewriteRelation = heap_openr(RewriteRelationName);
-
        tuple = SearchSysCacheTuple(REWRITENAME,
                                                                PointerGetDatum(ruleName),
                                                                0, 0, 0);
-
-       /*
-        * return whether or not the rewrite rule existed
-        */
-       heap_close(RewriteRelation);
        return HeapTupleIsValid(tuple);
 }
 
@@ -111,12 +99,12 @@ setRelhasrulesInRelation(Oid relationId, bool relhasrules)
         * 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));
 
-       relationRelation = heap_openr(RelationRelationName);
        ((Form_pg_class) GETSTRUCT(tuple))->relhasrules = relhasrules;
        heap_replace(relationRelation, &tuple->t_self, tuple, NULL);
 
@@ -126,7 +114,7 @@ setRelhasrulesInRelation(Oid relationId, bool relhasrules)
        CatalogCloseIndices(Num_pg_class_indices, idescs);
 
        pfree(tuple);
-       heap_close(relationRelation);
+       heap_close(relationRelation, RowExclusiveLock);
 }
 
 void
@@ -162,7 +150,7 @@ prs2_addToRelation(Oid relid,
        thisRule->actions = actions;
        thisRule->isInstead = isInstead;
 
-       relation = heap_open(relid);
+       relation = heap_open(relid, AccessShareLock);
 
        /*
         * modify or create a RuleLock cached by Relation
@@ -200,9 +188,7 @@ prs2_addToRelation(Oid relid,
                rulelock->numLocks++;
        }
 
-       heap_close(relation);
-
-       return;
+       heap_close(relation, AccessShareLock);
 }
 
 void
@@ -214,7 +200,7 @@ prs2_deleteFromRelation(Oid relid, Oid ruleId)
        int                     i;
        MemoryContext oldcxt;
 
-       relation = heap_open(relid);
+       relation = heap_open(relid, AccessShareLock);
        rulelock = relation->rd_rules;
        Assert(rulelock != NULL);
 
@@ -245,5 +231,5 @@ prs2_deleteFromRelation(Oid relid, Oid ruleId)
                rulelock->numLocks--;
        }
 
-       heap_close(relation);
+       heap_close(relation, AccessShareLock);
 }
index de0d803efe23215870a2d0d24a5df977e51506b2..b435dd53cac10ed46b5c9b3b20620769ae41e296 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.61 1999/07/17 20:17:40 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.62 1999/09/18 19:07:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -109,7 +109,7 @@ RelationGetBufferWithBuffer(Relation relation,
        {
                if (!BufferIsLocal(buffer))
                {
-                       LockRelId  *lrelId = &(((LockInfo) (relation->lockInfo))->lockRelId);
+                       LockRelId  *lrelId = & relation->rd_lockInfo.lockRelId;
 
                        bufHdr = &BufferDescriptors[buffer - 1];
                        SpinAcquire(BufMgrLock);
@@ -813,6 +813,7 @@ FlushBuffer(Buffer buffer, bool release)
        status = smgrflush(DEFAULT_SMGR, bufrel, bufHdr->tag.blockNum,
                                           (char *) MAKE_PTR(bufHdr->data));
 
+       /* drop relcache refcount incremented by RelationIdCacheGetRelation */
        RelationDecrementReferenceCount(bufrel);
 
        if (status == SM_FAIL)
@@ -993,6 +994,7 @@ BufferSync()
                                                elog(ERROR, "BufferSync: write error %u for %s",
                                                         bufHdr->tag.blockNum, bufHdr->sb_relname);
                                        }
+                                       /* drop refcount from RelationIdCacheGetRelation */
                                        if (reln != (Relation) NULL)
                                                RelationDecrementReferenceCount(reln);
                                        continue;
@@ -1047,6 +1049,7 @@ BufferSync()
                                 */
                                if (!(bufHdr->flags & BM_JUST_DIRTIED))
                                        bufHdr->flags &= ~BM_DIRTY;
+                               /* drop refcount from RelationIdCacheGetRelation */
                                if (reln != (Relation) NULL)
                                        RelationDecrementReferenceCount(reln);
                        }
@@ -1282,14 +1285,16 @@ BufferGetRelation(Buffer buffer)
        /* XXX should be a critical section */
        relid = BufferDescriptors[buffer - 1].tag.relId.relId;
        relation = RelationIdGetRelation(relid);
+       Assert(relation);
 
+       /* drop relcache refcount incremented by RelationIdGetRelation */
        RelationDecrementReferenceCount(relation);
 
        if (RelationHasReferenceCountZero(relation))
        {
 
                /*
-                * elog(NOTICE, "BufferGetRelation: 0->1");
+                * XXX why??
                 */
 
                RelationIncrementReferenceCount(relation);
@@ -1342,7 +1347,6 @@ BufferReplace(BufferDesc *bufHdr, bool bufferLockHeld)
        }
        else
        {
-
                /* blind write always flushes */
                status = smgrblindwrt(DEFAULT_SMGR, bufHdr->sb_dbname,
                                                          bufHdr->sb_relname, bufdb, bufrel,
@@ -1350,6 +1354,7 @@ BufferReplace(BufferDesc *bufHdr, bool bufferLockHeld)
                                                          (char *) MAKE_PTR(bufHdr->data));
        }
 
+       /* drop relcache refcount incremented by RelationIdCacheGetRelation */
        if (reln != (Relation) NULL)
                RelationDecrementReferenceCount(reln);
 
index a6a2d456b26c6ef920bed9e2da9f114427e6ecc3..e003595beda6d0395bccdfd9ac0665468b205e0c 100644 (file)
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/buffer/localbuf.c,v 1.26 1999/07/17 20:17:41 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/buffer/localbuf.c,v 1.27 1999/09/18 19:07:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -109,6 +109,8 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
                smgrwrite(DEFAULT_SMGR, bufrel, bufHdr->tag.blockNum,
                                  (char *) MAKE_PTR(bufHdr->data));
                LocalBufferFlushCount++;
+
+               /* drop relcache refcount incremented by RelationIdCacheGetRelation */
                RelationDecrementReferenceCount(bufrel);
        }
 
@@ -187,6 +189,8 @@ FlushLocalBuffer(Buffer buffer, bool release)
        smgrflush(DEFAULT_SMGR, bufrel, bufHdr->tag.blockNum,
                          (char *) MAKE_PTR(bufHdr->data));
        LocalBufferFlushCount++;
+
+       /* drop relcache refcount incremented by RelationIdCacheGetRelation */
        RelationDecrementReferenceCount(bufrel);
 
        Assert(LocalRefCount[bufid] > 0);
@@ -260,6 +264,8 @@ LocalBufferSync(void)
                        smgrwrite(DEFAULT_SMGR, bufrel, buf->tag.blockNum,
                                          (char *) MAKE_PTR(buf->data));
                        LocalBufferFlushCount++;
+
+                       /* drop relcache refcount from RelationIdCacheGetRelation */
                        RelationDecrementReferenceCount(bufrel);
 
                        buf->tag.relId.relId = InvalidOid;
index 6b8765bb81ca605567ba4d815a2695d34a4624d4..f59e99d7fbe90fd5b0156749b01ef84c7c83a053 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.58 1999/07/19 07:07:23 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.59 1999/09/18 19:07:32 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -139,13 +139,16 @@ inv_create(int flags)
 
        /* make the relation visible in this transaction */
        CommandCounterIncrement();
-       r = heap_openr(objname);
 
-       if (!RelationIsValid(r))
-       {
-               elog(ERROR, "cannot create large object on %s under inversion",
-                        smgrout(DEFAULT_SMGR));
-       }
+       /*--------------------
+        * We hold AccessShareLock on any large object we have open
+        * by inv_create or inv_open; it is released by inv_close.
+        * Note this will not conflict with ExclusiveLock or ShareLock
+        * that we acquire when actually reading/writing; it just prevents
+        * deletion of the large object while we have it open.
+        *--------------------
+        */
+       r = heap_openr(objname, AccessShareLock);
 
        /*
         * Now create a btree index on the relation's olastbyte attribute to
@@ -205,10 +208,7 @@ inv_open(Oid lobjId, int flags)
        char       *indname;
        Relation        indrel;
 
-       r = heap_open(lobjId);
-
-       if (!RelationIsValid(r))
-               return (LargeObjectDesc *) NULL;
+       r = heap_open(lobjId, AccessShareLock);
 
        indname = pstrdup((r->rd_rel->relname).data);
 
@@ -262,8 +262,8 @@ inv_close(LargeObjectDesc *obj_desc)
                obj_desc->iscan = NULL;
        }
 
-       heap_close(obj_desc->heap_r);
        index_close(obj_desc->index_r);
+       heap_close(obj_desc->heap_r, AccessShareLock);
 
        pfree(obj_desc);
 }
@@ -279,7 +279,7 @@ inv_destroy(Oid lobjId)
        Relation        r;
 
        r = (Relation) RelationIdGetRelation(lobjId);
-       if (!RelationIsValid(r) || r->rd_rel->relkind == RELKIND_INDEX)
+       if (!RelationIsValid(r) || r->rd_rel->relkind != RELKIND_LOBJECT)
                return -1;
 
        heap_destroy_with_catalog(r->rd_rel->relname.data);
@@ -497,7 +497,7 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes)
 
        if (!(obj_desc->flags & IFS_WRLOCK))
        {
-               LockRelation(obj_desc->heap_r, ShareLock);
+               LockRelation(obj_desc->heap_r, ExclusiveLock);
                obj_desc->flags |= (IFS_WRLOCK | IFS_RDLOCK);
        }
 
index 839533952b5cf4306e9ad5dad366302c4ff38700..2aaaf69e83e9d67a4e9c98c9cea5e75d4fc91030 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.34 1999/09/04 18:42:14 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.35 1999/09/18 19:07:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 
 #include "postgres.h"
+
 #include "access/transam.h"
 #include "catalog/catalog.h"
+#include "miscadmin.h"
 #include "utils/inval.h"
 
-extern Oid     MyDatabaseId;
 
 static LOCKMASK LockConflicts[] = {
        (int) NULL,
@@ -106,37 +107,25 @@ InitLockTable()
 /*
  * RelationInitLockInfo
  *             Initializes the lock information in a relation descriptor.
+ *
+ *             relcache.c must call this during creation of any reldesc.
  */
 void
 RelationInitLockInfo(Relation relation)
 {
-       LockInfo        info;
        char       *relname;
-       MemoryContext oldcxt;
-       extern Oid      MyDatabaseId;   /* XXX use include */
-       extern GlobalMemory CacheCxt;
 
        Assert(RelationIsValid(relation));
        Assert(OidIsValid(RelationGetRelid(relation)));
 
-       info = (LockInfo) relation->lockInfo;
-
-       if (LockInfoIsValid(info))
-               return;
-
        relname = (char *) RelationGetRelationName(relation);
 
-       oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
-       info = (LockInfo) palloc(sizeof(LockInfoData));
-       MemoryContextSwitchTo(oldcxt);
+       relation->rd_lockInfo.lockRelId.relId = RelationGetRelid(relation);
 
-       info->lockRelId.relId = RelationGetRelid(relation);
        if (IsSharedSystemRelationName(relname))
-               info->lockRelId.dbId = InvalidOid;
+               relation->rd_lockInfo.lockRelId.dbId = InvalidOid;
        else
-               info->lockRelId.dbId = MyDatabaseId;
-
-       relation->lockInfo = (Pointer) info;
+               relation->rd_lockInfo.lockRelId.dbId = MyDatabaseId;
 }
 
 /*
@@ -145,20 +134,14 @@ RelationInitLockInfo(Relation relation)
 void
 LockRelation(Relation relation, LOCKMODE lockmode)
 {
-       LockInfo        lockinfo;
        LOCKTAG         tag;
 
        if (LockingDisabled())
                return;
 
-       if (!LockInfoIsValid(relation->lockInfo))
-               RelationInitLockInfo(relation);
-
-       lockinfo = (LockInfo) relation->lockInfo;
-
        MemSet(&tag, 0, sizeof(tag));
-       tag.relId = lockinfo->lockRelId.relId;
-       tag.dbId = lockinfo->lockRelId.dbId;
+       tag.relId = relation->rd_lockInfo.lockRelId.relId;
+       tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
        tag.objId.blkno = InvalidBlockNumber;
 
        LockAcquire(LockTableId, &tag, lockmode);
@@ -180,28 +163,17 @@ LockRelation(Relation relation, LOCKMODE lockmode)
 void
 UnlockRelation(Relation relation, LOCKMODE lockmode)
 {
-       LockInfo        lockinfo;
        LOCKTAG         tag;
 
        if (LockingDisabled())
                return;
 
-       lockinfo = (LockInfo) relation->lockInfo;
-
-       if (!LockInfoIsValid(lockinfo))
-       {
-               elog(ERROR,
-                        "Releasing a lock on %s with invalid lock information",
-                        RelationGetRelationName(relation));
-       }
-
        MemSet(&tag, 0, sizeof(tag));
-       tag.relId = lockinfo->lockRelId.relId;
-       tag.dbId = lockinfo->lockRelId.dbId;
+       tag.relId = relation->rd_lockInfo.lockRelId.relId;
+       tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
        tag.objId.blkno = InvalidBlockNumber;
 
        LockRelease(LockTableId, &tag, lockmode);
-       return;
 }
 
 /*
@@ -210,24 +182,17 @@ UnlockRelation(Relation relation, LOCKMODE lockmode)
 void
 LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
 {
-       LockInfo        lockinfo;
        LOCKTAG         tag;
 
        if (LockingDisabled())
                return;
 
-       if (!LockInfoIsValid(relation->lockInfo))
-               RelationInitLockInfo(relation);
-
-       lockinfo = (LockInfo) relation->lockInfo;
-
        MemSet(&tag, 0, sizeof(tag));
-       tag.relId = lockinfo->lockRelId.relId;
-       tag.dbId = lockinfo->lockRelId.dbId;
+       tag.relId = relation->rd_lockInfo.lockRelId.relId;
+       tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
        tag.objId.blkno = blkno;
 
        LockAcquire(LockTableId, &tag, lockmode);
-       return;
 }
 
 /*
@@ -236,28 +201,17 @@ LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
 void
 UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
 {
-       LockInfo        lockinfo;
        LOCKTAG         tag;
 
        if (LockingDisabled())
                return;
 
-       lockinfo = (LockInfo) relation->lockInfo;
-
-       if (!LockInfoIsValid(lockinfo))
-       {
-               elog(ERROR,
-                        "Releasing a lock on %s with invalid lock information",
-                        RelationGetRelationName(relation));
-       }
-
        MemSet(&tag, 0, sizeof(tag));
-       tag.relId = lockinfo->lockRelId.relId;
-       tag.dbId = lockinfo->lockRelId.dbId;
+       tag.relId = relation->rd_lockInfo.lockRelId.relId;
+       tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
        tag.objId.blkno = blkno;
 
        LockRelease(LockTableId, &tag, lockmode);
-       return;
 }
 
 void
@@ -274,7 +228,6 @@ XactLockTableInsert(TransactionId xid)
        tag.objId.xid = xid;
 
        LockAcquire(LockTableId, &tag, ExclusiveLock);
-       return;
 }
 
 void
@@ -291,7 +244,6 @@ XactLockTableDelete(TransactionId xid)
        tag.objId.xid = xid;
 
        LockRelease(LockTableId, &tag, ExclusiveLock);
-       return;
 }
 
 void
@@ -316,6 +268,4 @@ XactLockTableWait(TransactionId xid)
         */
        if (!TransactionIdDidCommit(xid) && !TransactionIdDidAbort(xid))
                TransactionIdAbort(xid);
-
-       return;
 }
index 427cc749c84079879b50221c886063816084a9b5..3f5322c9f08d16b67b1d4e51b020bd7393ce9ad7 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.61 1999/07/17 20:17:46 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.62 1999/09/18 19:07:38 tgl Exp $
  *
  * NOTES
  *       Outside modules can create a lock table and acquire/release
@@ -596,7 +596,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
        if (!result)
        {
                elog(NOTICE, "LockAcquire: xid table corrupted");
-               return STATUS_ERROR;
+               return FALSE;
        }
 
        /*
@@ -1117,7 +1117,7 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
                        TPRINTF(TRACE_USERLOCKS, "LockRelease: no lock with this tag");
                else
 #endif
-                       elog(NOTICE, "LockReplace: xid table corrupted");
+                       elog(NOTICE, "LockRelease: xid table corrupted");
                return FALSE;
        }
        XID_PRINT("LockRelease: found", result);
index 8c1ac556149a590bdaf25a54c277505ec20babb3..29b4fb527c66eed7a1ba59d3af290eafc090dc02 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.64 1999/07/16 04:59:55 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.65 1999/09/18 19:07:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -165,38 +165,39 @@ ProcessUtility(Node *parsetree,
                case T_DestroyStmt:
                        {
                                DestroyStmt *stmt = (DestroyStmt *) parsetree;
-                               List       *arg;
                                List       *args = stmt->relNames;
-                               Relation        rel;
+                               List       *arg;
 
                                PS_SET_STATUS(commandTag = "DROP");
                                CHECK_IF_ABORTED();
 
+                               /* check as much as we can before we start dropping ... */
                                foreach(arg, args)
                                {
+                                       Relation        rel;
+
                                        relname = strVal(lfirst(arg));
                                        if (!allowSystemTableMods && IsSystemRelationName(relname))
                                                elog(ERROR, "class \"%s\" is a system catalog",
                                                         relname);
-                                       rel = heap_openr(relname);
-                                       if (RelationIsValid(rel))
-                                       {
-                                               if (stmt->sequence &&
-                                                       rel->rd_rel->relkind != RELKIND_SEQUENCE)
-                                                       elog(ERROR, "Use DROP TABLE to drop table '%s'",
-                                                                relname);
-                                               if (!(stmt->sequence) &&
-                                                       rel->rd_rel->relkind == RELKIND_SEQUENCE)
-                                                       elog(ERROR, "Use DROP SEQUENCE to drop sequence '%s'",
-                                                                relname);
-                                               heap_close(rel);
-                                       }
+                                       rel = heap_openr(relname, AccessExclusiveLock);
+                                       if (stmt->sequence &&
+                                               rel->rd_rel->relkind != RELKIND_SEQUENCE)
+                                               elog(ERROR, "Use DROP TABLE to drop table '%s'",
+                                                        relname);
+                                       if (!(stmt->sequence) &&
+                                               rel->rd_rel->relkind == RELKIND_SEQUENCE)
+                                               elog(ERROR, "Use DROP SEQUENCE to drop sequence '%s'",
+                                                        relname);
+                                       /* close rel, but keep lock until end of xact */
+                                       heap_close(rel, NoLock);
 #ifndef NO_SECURITY
                                        if (!pg_ownercheck(userName, relname, RELNAME))
                                                elog(ERROR, "you do not own class \"%s\"",
                                                         relname);
 #endif
                                }
+                               /* OK, terminate 'em all */
                                foreach(arg, args)
                                {
                                        relname = strVal(lfirst(arg));
index 2ef45f63e425059d369c1af2f5896c12fe7a030f..1a851cf7e5f7c4e52cf45d38722b2eb2d2313393 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/not_in.c,v 1.20 1999/07/17 20:17:58 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/not_in.c,v 1.21 1999/09/18 19:07:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -58,12 +58,7 @@ int4notin(int32 not_in_arg, char *relation_and_attr)
 
        /* Open the relation and get a relation descriptor */
 
-       relation_to_scan = heap_openr(relation);
-       if (!RelationIsValid(relation_to_scan))
-       {
-               elog(ERROR, "int4notin: unknown relation %s",
-                        relation);
-       }
+       relation_to_scan = heap_openr(relation, AccessShareLock);
 
        /* Find the column to search */
 
@@ -95,7 +90,9 @@ int4notin(int32 not_in_arg, char *relation_and_attr)
        }
 
        /* close the relation */
-       heap_close(relation_to_scan);
+       heap_endscan(scan_descriptor);
+       heap_close(relation_to_scan, AccessShareLock);
+
        return retval;
 }
 
index 754eea3a96e933522b9ca007a38b243660cc2991..b3179e864c122526b1e6806f6a3f85ac33a7421f 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.42 1999/07/17 20:17:59 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.43 1999/09/18 19:07:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -78,7 +78,7 @@ regprocin(char *pro_name_or_oid)
                                                                   (RegProcedure) F_NAMEEQ,
                                                                   PointerGetDatum(pro_name_or_oid));
 
-                       hdesc = heap_openr(ProcedureRelationName);
+                       hdesc = heap_openr(ProcedureRelationName, AccessShareLock);
                        idesc = index_openr(ProcedureNameIndex);
 
                        sd = index_beginscan(idesc, false, 1, skey);
@@ -102,6 +102,7 @@ regprocin(char *pro_name_or_oid)
                        index_endscan(sd);
                        pfree(sd);
                        index_close(idesc);
+                       heap_close(hdesc, AccessShareLock);
 
                        if (matches > 1)
                                elog(ERROR, "There is more than one procedure named %s.\n\tSupply the pg_proc oid inside single quotes.", pro_name_or_oid);
@@ -116,13 +117,7 @@ regprocin(char *pro_name_or_oid)
                ScanKeyData key;
                bool            isnull;
 
-               proc = heap_openr(ProcedureRelationName);
-               if (!RelationIsValid(proc))
-               {
-                       elog(ERROR, "regprocin: could not open %s",
-                                ProcedureRelationName);
-                       return 0;
-               }
+               proc = heap_openr(ProcedureRelationName, AccessShareLock);
                ScanKeyEntryInitialize(&key,
                                                           (bits16) 0,
                                                           (AttrNumber) 1,
@@ -132,8 +127,8 @@ regprocin(char *pro_name_or_oid)
                procscan = heap_beginscan(proc, 0, SnapshotNow, 1, &key);
                if (!HeapScanIsValid(procscan))
                {
-                       heap_close(proc);
-                       elog(ERROR, "regprocin: could not being scan of %s",
+                       heap_close(proc, AccessShareLock);
+                       elog(ERROR, "regprocin: could not begin scan of %s",
                                 ProcedureRelationName);
                        return 0;
                }
@@ -151,7 +146,7 @@ regprocin(char *pro_name_or_oid)
                        result = (RegProcedure) 0;
 
                heap_endscan(procscan);
-               heap_close(proc);
+               heap_close(proc, AccessShareLock);
        }
 
        return (int32) result;
@@ -193,12 +188,7 @@ regprocout(RegProcedure proid)
                HeapScanDesc procscan;
                ScanKeyData key;
 
-               proc = heap_openr(ProcedureRelationName);
-               if (!RelationIsValid(proc))
-               {
-                       elog(ERROR, "regprocout: could not open %s", ProcedureRelationName);
-                       return 0;
-               }
+               proc = heap_openr(ProcedureRelationName, AccessShareLock);
                ScanKeyEntryInitialize(&key,
                                                           (bits16) 0,
                                                           (AttrNumber) ObjectIdAttributeNumber,
@@ -208,8 +198,8 @@ regprocout(RegProcedure proid)
                procscan = heap_beginscan(proc, 0, SnapshotNow, 1, &key);
                if (!HeapScanIsValid(procscan))
                {
-                       heap_close(proc);
-                       elog(ERROR, "regprocout: could not being scan of %s",
+                       heap_close(proc, AccessShareLock);
+                       elog(ERROR, "regprocout: could not begin scan of %s",
                                 ProcedureRelationName);
                        return 0;
                }
@@ -232,8 +222,7 @@ regprocout(RegProcedure proid)
                        result[1] = '\0';
                }
                heap_endscan(procscan);
-               heap_close(proc);
-               return result;
+               heap_close(proc, AccessShareLock);
        }
 
        return result;
index 1b2d58c075ed487de5fa54f1560f196adbb6baac..e14e5375553b3094f7ab4b3987d57ebf2db6bb0c 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.40 1999/09/09 02:35:58 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.41 1999/09/18 19:07:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -598,7 +598,7 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid typid, int32 typmod,
        HeapTuple       typeTuple;
        FmgrInfo        inputproc;
 
-       rel = heap_openr(StatisticRelationName);
+       rel = heap_openr(StatisticRelationName, AccessShareLock);
 
        key[0].sk_argument = ObjectIdGetDatum(relid);
        key[1].sk_argument = Int16GetDatum((int16) attnum);
@@ -609,7 +609,7 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid typid, int32 typmod,
        {
                /* no such stats entry */
                heap_endscan(scan);
-               heap_close(rel);
+               heap_close(rel, AccessShareLock);
                return false;
        }
 
@@ -694,7 +694,7 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid typid, int32 typmod,
        }
 
        heap_endscan(scan);
-       heap_close(rel);
+       heap_close(rel, AccessShareLock);
        return true;
 }
 
index 05bc16b92aff49c566fb863de9886cf8befc911d..46dbca9d6984e038b18e58e97bf4f229c174d594 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.25 1999/07/17 20:18:00 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.26 1999/09/18 19:07:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -100,8 +100,7 @@ SetDefine(char *querystr, char *typename)
                        replNull[i] = ' ';
 
                /* change the pg_proc tuple */
-               procrel = heap_openr(ProcedureRelationName);
-               LockRelation(procrel, AccessExclusiveLock);
+               procrel = heap_openr(ProcedureRelationName, RowExclusiveLock);
 
                tup = SearchSysCacheTuple(PROOID,
                                                                  ObjectIdGetDatum(setoid),
@@ -131,8 +130,7 @@ SetDefine(char *querystr, char *typename)
                        CatalogIndexInsert(idescs, Num_pg_proc_indices, procrel, newtup);
                        CatalogCloseIndices(Num_pg_proc_indices, idescs);
                }
-               UnlockRelation(procrel, AccessExclusiveLock);
-               heap_close(procrel);
+               heap_close(procrel, RowExclusiveLock);
        }
        return setoid;
 }
index f6ef0fecac266eb116cb82eff2759c0a49045e6d..22d933bb37a3f4886e4875714ec453c3d7d38223 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.48 1999/07/17 20:18:01 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.49 1999/09/18 19:07:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -130,7 +130,8 @@ CatalogCacheInitializeCache(struct catcache * cache,
        /* ----------------
         *      If no relation was passed we must open it to get access to
         *      its fields.  If one of the other caches has already opened
-        *      it we use heap_open() instead of heap_openr()
+        *      it we use heap_open() instead of heap_openr().
+        *      XXX is that really worth the trouble of checking?
         * ----------------
         */
        if (!RelationIsValid(relation))
@@ -155,9 +156,9 @@ CatalogCacheInitializeCache(struct catcache * cache,
                 * ----------------
                 */
                if (cp)
-                       relation = heap_open(cp->relationId);
+                       relation = heap_open(cp->relationId, NoLock);
                else
-                       relation = heap_openr(cache->cc_relname);
+                       relation = heap_openr(cache->cc_relname, NoLock);
 
                didopen = 1;
        }
@@ -217,7 +218,7 @@ CatalogCacheInitializeCache(struct catcache * cache,
         * ----------------
         */
        if (didopen)
-               heap_close(relation);
+               heap_close(relation, NoLock);
 
        /* ----------------
         *      initialize index information for the cache.  this
@@ -891,10 +892,10 @@ SearchSysCache(struct catcache * cache,
                DLMoveToFront(elt);
 
 #ifdef CACHEDEBUG
-               relation = heap_open(cache->relationId);
+               relation = heap_open(cache->relationId, NoLock);
                CACHE3_elog(DEBUG, "SearchSysCache(%s): found in bucket %d",
                                        RelationGetRelationName(relation), hash);
-               heap_close(relation);
+               heap_close(relation, NoLock);
 #endif  /* CACHEDEBUG */
 
                return ct->ct_tup;
@@ -925,7 +926,7 @@ SearchSysCache(struct catcache * cache,
         *      open the relation associated with the cache
         * ----------------
         */
-       relation = heap_open(cache->relationId);
+       relation = heap_open(cache->relationId, AccessShareLock);
        CACHE2_elog(DEBUG, "SearchSysCache(%s)",
                                RelationGetRelationName(relation));
 
@@ -1082,7 +1083,7 @@ SearchSysCache(struct catcache * cache,
         *      and return the tuple we found (or NULL)
         * ----------------
         */
-       heap_close(relation);
+       heap_close(relation, AccessShareLock);
 
        MemoryContextSwitchTo(oldcxt);
        return ntp;
@@ -1146,8 +1147,6 @@ RelationInvalidateCatalogCacheTuple(Relation relation,
                (*function) (ccp->id,
                                 CatalogCacheComputeTupleHashIndex(ccp, relation, tuple),
                                         &tuple->t_self);
-
-               heap_close(relation);
        }
 
        /* ----------------
index db685e751ebf68ec2dc4d0b51b29602109a22cea..afba41db108094e12a771688014257c7586f7ba6 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.72 1999/09/06 19:33:16 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.73 1999/09/18 19:07:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -337,7 +337,7 @@ scan_pg_rel_seq(RelationBuildDescInfo buildinfo)
         *      open pg_class and fetch a tuple
         * ----------------
         */
-       pg_class_desc = heap_openr(RelationRelationName);
+       pg_class_desc = heap_openr(RelationRelationName, AccessShareLock);
        pg_class_scan = heap_beginscan(pg_class_desc, 0, SnapshotNow, 1, &key);
        pg_class_tuple = heap_getnext(pg_class_scan, 0);
 
@@ -361,7 +361,7 @@ scan_pg_rel_seq(RelationBuildDescInfo buildinfo)
 
        /* all done */
        heap_endscan(pg_class_scan);
-       heap_close(pg_class_desc);
+       heap_close(pg_class_desc, AccessShareLock);
 
        return return_tuple;
 }
@@ -372,9 +372,7 @@ scan_pg_rel_ind(RelationBuildDescInfo buildinfo)
        Relation        pg_class_desc;
        HeapTuple       return_tuple;
 
-       pg_class_desc = heap_openr(RelationRelationName);
-       if (!IsInitProcessingMode())
-               LockRelation(pg_class_desc, AccessShareLock);
+       pg_class_desc = heap_openr(RelationRelationName, AccessShareLock);
 
        switch (buildinfo.infotype)
        {
@@ -389,18 +387,10 @@ scan_pg_rel_ind(RelationBuildDescInfo buildinfo)
 
                default:
                        elog(ERROR, "ScanPgRelation: bad buildinfo");
-
-                       /*
-                        * XXX I hope this is right.  It seems better than returning
-                        * an uninitialized value
-                        */
-                       return_tuple = NULL;
+                       return_tuple = NULL; /* keep compiler quiet */
        }
 
-       /* all done */
-       if (!IsInitProcessingMode())
-               UnlockRelation(pg_class_desc, AccessShareLock);
-       heap_close(pg_class_desc);
+       heap_close(pg_class_desc, AccessShareLock);
 
        return return_tuple;
 }
@@ -508,7 +498,7 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
         *      open pg_attribute and begin a scan
         * ----------------
         */
-       pg_attribute_desc = heap_openr(AttributeRelationName);
+       pg_attribute_desc = heap_openr(AttributeRelationName, AccessShareLock);
        pg_attribute_scan = heap_beginscan(pg_attribute_desc, 0, SnapshotNow, 1, &key);
 
        /* ----------------
@@ -544,7 +534,7 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
         * ----------------
         */
        heap_endscan(pg_attribute_scan);
-       heap_close(pg_attribute_desc);
+       heap_close(pg_attribute_desc, AccessShareLock);
 }
 
 static void
@@ -562,7 +552,7 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
 
        constr->has_not_null = false;
 
-       attrel = heap_openr(AttributeRelationName);
+       attrel = heap_openr(AttributeRelationName, AccessShareLock);
 
        for (i = 1; i <= relation->rd_rel->relnatts; i++)
        {
@@ -597,7 +587,7 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
                }
        }
 
-       heap_close(attrel);
+       heap_close(attrel, AccessShareLock);
 
        if (constr->has_not_null || ndef > 0 || relation->rd_rel->relchecks)
        {
@@ -677,7 +667,7 @@ RelationBuildRuleLock(Relation relation)
         *      open pg_attribute and begin a scan
         * ----------------
         */
-       pg_rewrite_desc = heap_openr(RewriteRelationName);
+       pg_rewrite_desc = heap_openr(RewriteRelationName, AccessShareLock);
        pg_rewrite_scan = heap_beginscan(pg_rewrite_desc, 0, SnapshotNow, 1, &key);
        pg_rewrite_tupdesc = RelationGetDescr(pg_rewrite_desc);
 
@@ -732,7 +722,7 @@ RelationBuildRuleLock(Relation relation)
         * ----------------
         */
        heap_endscan(pg_rewrite_scan);
-       heap_close(pg_rewrite_desc);
+       heap_close(pg_rewrite_desc, AccessShareLock);
 
        /* ----------------
         *      form a RuleLock and insert into relation
@@ -765,9 +755,9 @@ RelationBuildRuleLock(Relation relation)
  *     uint16                             rd_refcnt;    reference count
  *     Form_pg_am                         rd_am;                AM tuple
  *     Form_pg_class              rd_rel;               RELATION tuple
- *     Oid                                        rd_id;                relations's object id
- *     Pointer                            lockInfo;     ptr. to misc. info.
- *     TupleDesc                          rd_att;               tuple desciptor
+ *     Oid                                        rd_id;                relation's object id
+ *     LockInfoData               rd_lockInfo;  lock manager's info
+ *     TupleDesc                          rd_att;               tuple descriptor
  *
  *             Note: rd_ismem (rel is in-memory only) is currently unused
  *             by any part of the system.      someday this will indicate that
@@ -1048,14 +1038,18 @@ formrdesc(char *relationName,
         */
        RelationGetRelid(relation) = relation->rd_att->attrs[0]->attrelid;
 
+       /* ----------------
+        *      initialize the relation lock manager information
+        * ----------------
+        */
+       RelationInitLockInfo(relation);         /* see lmgr.c */
+
        /* ----------------
         *      add new reldesc to relcache
         * ----------------
         */
        RelationCacheInsert(relation);
 
-       RelationInitLockInfo(relation);
-
        /*
         * Determining this requires a scan on pg_class, but to do the scan
         * the rdesc for pg_class must already exist.  Therefore we must do
@@ -1074,9 +1068,13 @@ formrdesc(char *relationName,
 /* --------------------------------
  *             RelationIdCacheGetRelation
  *
- *             only try to get the reldesc by looking up the cache
- *             do not go to the disk.  this is used by BlockPrepareFile()
- *             and RelationIdGetRelation below.
+ *             Lookup a reldesc by OID.
+ *             Only try to get the reldesc by looking up the cache
+ *             do not go to the disk.
+ *
+ *             NB: relation ref count is incremented if successful.
+ *             Caller should eventually decrement count.  (Usually,
+ *             that happens by calling RelationClose().)
  * --------------------------------
  */
 Relation
@@ -1103,6 +1101,8 @@ RelationIdCacheGetRelation(Oid relationId)
 
 /* --------------------------------
  *             RelationNameCacheGetRelation
+ *
+ *             As above, but lookup by name.
  * --------------------------------
  */
 static Relation
@@ -1136,8 +1136,11 @@ RelationNameCacheGetRelation(char *relationName)
 /* --------------------------------
  *             RelationIdGetRelation
  *
- *             return a relation descriptor based on its id.
- *             return a cached value if possible
+ *             Lookup a reldesc by OID; make one if not already in cache.
+ *
+ *             NB: relation ref count is incremented, or set to 1 if new entry.
+ *             Caller should eventually decrement count.  (Usually,
+ *             that happens by calling RelationClose().)
  * --------------------------------
  */
 Relation
@@ -1176,8 +1179,7 @@ RelationIdGetRelation(Oid relationId)
 /* --------------------------------
  *             RelationNameGetRelation
  *
- *             return a relation descriptor based on its name.
- *             return a cached value if possible
+ *             As above, but lookup by name.
  * --------------------------------
  */
 Relation
@@ -1289,7 +1291,6 @@ RelationFlushRelation(Relation *relationPtr,
        /* Free all the subsidiary data structures of the relcache entry */
        FreeTupleDesc(relation->rd_att);
        FreeTriggerDesc(relation);
-       pfree(RelationGetLockInfo(relation));
        pfree(RelationGetForm(relation));
 
        /* If we're really done with the relcache entry, blow it away.
@@ -1530,10 +1531,10 @@ RelationRegisterRelation(Relation relation)
        if (oldcxt != (MemoryContext) CacheCxt)
                elog(NOIND, "RelationRegisterRelation: WARNING: Context != CacheCxt");
 
-       RelationCacheInsert(relation);
-
        RelationInitLockInfo(relation);
 
+       RelationCacheInsert(relation);
+
        /*
         * we've just created the relation. It is invisible to anyone else
         * before the transaction is committed. Setting rd_myxactonly allows
@@ -1692,7 +1693,7 @@ AttrDefaultFetch(Relation relation)
                                                   (RegProcedure) F_OIDEQ,
                                                   ObjectIdGetDatum(RelationGetRelid(relation)));
 
-       adrel = heap_openr(AttrDefaultRelationName);
+       adrel = heap_openr(AttrDefaultRelationName, AccessShareLock);
        irel = index_openr(AttrDefaultIndex);
        sd = index_beginscan(irel, false, 1, &skey);
        tuple.t_data = NULL;
@@ -1754,7 +1755,7 @@ AttrDefaultFetch(Relation relation)
        index_endscan(sd);
        pfree(sd);
        index_close(irel);
-       heap_close(adrel);
+       heap_close(adrel, AccessShareLock);
 }
 
 static void
@@ -1779,7 +1780,7 @@ RelCheckFetch(Relation relation)
                                                   (RegProcedure) F_OIDEQ,
                                                   ObjectIdGetDatum(RelationGetRelid(relation)));
 
-       rcrel = heap_openr(RelCheckRelationName);
+       rcrel = heap_openr(RelCheckRelationName, AccessShareLock);
        irel = index_openr(RelCheckIndex);
        sd = index_beginscan(irel, false, 1, &skey);
        tuple.t_data = NULL;
@@ -1834,8 +1835,7 @@ RelCheckFetch(Relation relation)
        index_endscan(sd);
        pfree(sd);
        index_close(irel);
-       heap_close(rcrel);
-
+       heap_close(rcrel, AccessShareLock);
 }
 
 /*
@@ -1929,9 +1929,6 @@ init_irels(void)
                /* the file descriptor is not yet opened */
                ird->rd_fd = -1;
 
-               /* lock info is not initialized */
-               ird->lockInfo = (char *) NULL;
-
                /* next, read the access method tuple form */
                if ((nread = FileRead(fd, (char *) &len, sizeof(len))) != sizeof(len))
                {
@@ -2038,8 +2035,9 @@ init_irels(void)
 
                ird->rd_support = support;
 
-               RelationCacheInsert(ird);
                RelationInitLockInfo(ird);
+
+               RelationCacheInsert(ird);
        }
 }
 
index c9c7770f8ccbb7a5e531967c51be16906d2cf093..204f13ffab9f34aa3a92a1a659d37f86cb76ce90 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.35 1999/09/04 22:00:30 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.36 1999/09/18 19:07:55 tgl Exp $
  *
  * NOTES
  *       These routines allow the parser/planner/executor to perform
@@ -575,11 +575,19 @@ SearchSysCacheGetAttribute(int cacheId,
        Datum           attributeValue;
        void       *returnValue;
 
-       tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
+       /*
+        * Open the relation first, to ensure we are in sync with SI inval
+        * events --- we don't want the tuple found in the cache to be
+        * invalidated out from under us.
+        */
        cacheName = cacheinfo[cacheId].name;
+       relation = heap_openr(cacheName, AccessShareLock);
+
+       tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
 
        if (!HeapTupleIsValid(tp))
        {
+               heap_close(relation, AccessShareLock);
 #ifdef CACHEDEBUG
                elog(DEBUG,
                         "SearchSysCacheGetAttribute: Lookup in %s(%d) failed",
@@ -588,8 +596,6 @@ SearchSysCacheGetAttribute(int cacheId,
                return NULL;
        }
 
-       relation = heap_openr(cacheName);
-
        if (attributeNumber < 0 &&
                attributeNumber > FirstLowInvalidHeapAttributeNumber)
        {
@@ -604,6 +610,7 @@ SearchSysCacheGetAttribute(int cacheId,
        }
        else
        {
+               heap_close(relation, AccessShareLock);
                elog(ERROR,
                         "SearchSysCacheGetAttribute: Bad attr # %d in %s(%d)",
                         attributeNumber, cacheName, cacheId);
@@ -617,11 +624,11 @@ SearchSysCacheGetAttribute(int cacheId,
 
        if (isNull)
        {
-
                /*
                 * Used to be an elog(DEBUG, ...) here and a claim that it should
                 * be a FATAL error, I don't think either is warranted -mer 6/9/92
                 */
+               heap_close(relation, AccessShareLock);
                return NULL;
        }
 
@@ -639,6 +646,6 @@ SearchSysCacheGetAttribute(int cacheId,
                returnValue = (void *) tmp;
        }
 
-       heap_close(relation);
+       heap_close(relation, AccessShareLock);
        return returnValue;
 }
index d48d8b8840aefc08b77fe7b2678430831f44f044..dcf2814171b583600a8b974c9b43dfb63eeb1ab6 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.31 1999/07/17 20:18:04 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.32 1999/09/18 19:08:01 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -56,8 +56,13 @@ fmgr_dynamic(Oid procedureId, int *pronargs)
 
        /*
         * The procedure isn't a builtin, so we'll have to do a catalog lookup
-        * to find its pg_proc entry.
+        * to find its pg_proc entry.  Moreover, since probin is varlena, we're
+        * going to have to use heap_getattr, which means we need the reldesc,
+        * which means we need to open the relation.  So we might as well do that
+        * first and get the benefit of SI inval if needed.
         */
+       rel = heap_openr(ProcedureRelationName, AccessShareLock);
+
        procedureTuple = SearchSysCacheTuple(PROOID,
                                                                                 ObjectIdGetDatum(procedureId),
                                                                                 0, 0, 0);
@@ -71,36 +76,24 @@ fmgr_dynamic(Oid procedureId, int *pronargs)
        procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
        proname = procedureStruct->proname.data;
        pronargs_save = *pronargs = procedureStruct->pronargs;
-
-       /*
-        * Extract the procedure info from the pg_proc tuple. Since probin is
-        * varlena, do a amgetattr() on the procedure tuple.  To do that, we
-        * need the rel for the procedure relation, so...
-        */
-
-       /* open pg_procedure */
-
-       rel = heap_openr(ProcedureRelationName);
-       if (!RelationIsValid(rel))
-       {
-               elog(ERROR, "fmgr: Could not open relation %s",
-                        ProcedureRelationName);
-               return (func_ptr) NULL;
-       }
        probinattr = heap_getattr(procedureTuple,
                                                          Anum_pg_proc_probin,
                                                          RelationGetDescr(rel), &isnull);
        if (!PointerIsValid(probinattr) /* || isnull */ )
        {
-               heap_close(rel);
+               heap_close(rel, AccessShareLock);
                elog(ERROR, "fmgr: Could not extract probin for %u from %s",
                         procedureId, ProcedureRelationName);
                return (func_ptr) NULL;
        }
        probinstring = textout((struct varlena *) probinattr);
 
+       heap_close(rel, AccessShareLock);
+
        user_fn = handle_load(probinstring, proname);
 
+       pfree(probinstring);
+
        procedureId_save = procedureId;
        user_fn_save = user_fn;
 
index 39270f35c0c4292a9d0ef3ea064f62011a68677e..321ab943aeac394811e8d136d75ba550c696dece 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/misc/Attic/database.c,v 1.28 1999/07/17 20:18:11 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/misc/Attic/database.c,v 1.29 1999/09/18 19:08:07 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -43,10 +43,7 @@ GetDatabaseInfo(char *name, int4 *owner, char *path)
        HeapScanDesc scan;
        ScanKeyData scanKey;
 
-       dbrel = heap_openr(DatabaseRelationName);
-       if (!RelationIsValid(dbrel))
-               elog(FATAL, "GetDatabaseInfo: cannot open relation \"%-.*s\"",
-                        DatabaseRelationName);
+       dbrel = heap_openr(DatabaseRelationName, AccessShareLock);
 
        ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_database_datname,
                                                   F_NAMEEQ, NameGetDatum(name));
@@ -71,6 +68,7 @@ GetDatabaseInfo(char *name, int4 *owner, char *path)
        {
                elog(NOTICE, "GetDatabaseInfo: %s entry not found %s",
                         DatabaseRelationName, name);
+               heap_close(dbrel, AccessShareLock);
                return TRUE;
        }
 
@@ -88,7 +86,7 @@ GetDatabaseInfo(char *name, int4 *owner, char *path)
        memcpy(dbpath, VARDATA(dbtext), (VARSIZE(dbtext) - VARHDRSZ));
        *(dbpath + (VARSIZE(dbtext) - VARHDRSZ)) = '\0';
 
-       heap_close(dbrel);
+       heap_close(dbrel, AccessShareLock);
 
        owner = palloc(sizeof(Oid));
        *owner = dbowner;
index 8c1461122fcbf7c239c57b59609b6f185a7af8cb..b6dccc33fa8d7c69f4c9f38be84bf382b264aaf3 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: heapam.h,v 1.45 1999/07/16 17:07:26 momjian Exp $
+ * $Id: heapam.h,v 1.46 1999/09/18 19:08:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,6 +18,7 @@
 #include "access/relscan.h"
 #include "access/tupmacs.h"
 #include "storage/block.h"
+#include "storage/lmgr.h"
 #include "utils/rel.h"
 #include "utils/tqual.h"
 
@@ -246,9 +247,9 @@ extern HeapAccessStatistics heap_access_stats;      /* in stats.c */
 
 /* heapam.c */
 
-extern Relation heap_open(Oid relationId);
-extern Relation heap_openr(char *relationName);
-extern void heap_close(Relation relation);
+extern Relation heap_open(Oid relationId, LOCKMODE lockmode);
+extern Relation heap_openr(char *relationName, LOCKMODE lockmode);
+extern void heap_close(Relation relation, LOCKMODE lockmode);
 extern HeapScanDesc heap_beginscan(Relation relation, int atend,
                           Snapshot snapshot, unsigned nkeys, ScanKey key);
 extern void heap_rescan(HeapScanDesc scan, bool scanFromEnd, ScanKey key);
index 98d8be3369d01802141091f9eb895d6807d35066..b98f0fb820f057834821273d52b50fe93579761c 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: buf_internals.h,v 1.31 1999/07/16 17:07:37 momjian Exp $
+ * $Id: buf_internals.h,v 1.32 1999/09/18 19:08:18 tgl Exp $
  *
  * NOTE
  *             If BUFFERPAGE0 is defined, then 0 will be used as a
@@ -64,8 +64,8 @@ struct buftag
 
 #define INIT_BUFFERTAG(a,xx_reln,xx_blockNum) \
 ( \
-       (a)->blockNum = xx_blockNum, \
-       (a)->relId = ((LockInfo)(xx_reln->lockInfo))->lockRelId \
+       (a)->blockNum = (xx_blockNum), \
+       (a)->relId = (xx_reln)->rd_lockInfo.lockRelId \
 )
 
 #define BAD_BUFFER_ID(bid) ((bid<1) || (bid>(NBuffers)))
index 8903af8ec6bd43396d62e1d87c264a5eac7a7eb1..302bedb6771d115a78d2a8a551d583b60ccc7786 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: lmgr.h,v 1.22 1999/07/15 23:04:11 momjian Exp $
+ * $Id: lmgr.h,v 1.23 1999/09/18 19:08:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "storage/lock.h"
 #include "utils/rel.h"
 
+/* These are the valid values of type LOCKMODE: */
+
+/* NoLock is not a lock mode, but a flag value meaning "don't get a lock" */
+#define NoLock                                 0
+
 #define AccessShareLock                        1               /* SELECT */
 #define RowShareLock                   2               /* SELECT FOR UPDATE */
 #define RowExclusiveLock               3               /* INSERT, UPDATE, DELETE */
 extern LOCKMETHOD LockTableId;
 
 
-typedef struct LockRelId
-{
-       Oid                     relId;                  /* a relation identifier */
-       Oid                     dbId;                   /* a database identifier */
-} LockRelId;
-
-typedef struct LockInfoData
-{
-       LockRelId       lockRelId;
-} LockInfoData;
-
-typedef LockInfoData *LockInfo;
-
-#define LockInfoIsValid(lockinfo)      PointerIsValid(lockinfo)
-
 extern LOCKMETHOD InitLockTable(void);
 extern void RelationInitLockInfo(Relation relation);
 
index c95f51e89d1e523af92d2c3a3ad2f83dc290c392..f2789b39e09d15717749598430fe8049f47d09aa 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: rel.h,v 1.25 1999/07/16 17:07:40 momjian Exp $
+ * $Id: rel.h,v 1.26 1999/09/18 19:08:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "rewrite/prs2lock.h"
 #include "storage/fd.h"
 
+
+/*
+ * LockRelId and LockInfo really belong to lmgr.h, but it's more convenient
+ * to declare them here so we can have a LockInfoData field in a Relation.
+ */
+
+typedef struct LockRelId
+{
+       Oid                     relId;                  /* a relation identifier */
+       Oid                     dbId;                   /* a database identifier */
+} LockRelId;
+
+typedef struct LockInfoData
+{
+       LockRelId       lockRelId;
+} LockInfoData;
+
+typedef LockInfoData *LockInfo;
+
+
 typedef struct Trigger
 {
        char       *tgname;
@@ -44,20 +64,21 @@ typedef struct TriggerDesc
        Trigger    *triggers;
 } TriggerDesc;
 
+
 typedef struct RelationData
 {
        File            rd_fd;                  /* open file descriptor */
        int                     rd_nblocks;             /* number of blocks in rel */
        uint16          rd_refcnt;              /* reference count */
-       bool            rd_myxactonly;  /* uses the local buffer mgr */
+       bool            rd_myxactonly;  /* rel uses the local buffer mgr */
        bool            rd_isnailed;    /* rel is nailed in cache */
        bool            rd_isnoname;    /* rel has no name */
        bool            rd_nonameunlinked;              /* noname rel already unlinked */
        Form_pg_am      rd_am;                  /* AM tuple */
        Form_pg_class rd_rel;           /* RELATION tuple */
-       Oid                     rd_id;                  /* relations's object id */
-       Pointer         lockInfo;               /* ptr. to misc. info. */
-       TupleDesc       rd_att;                 /* tuple desciptor */
+       Oid                     rd_id;                  /* relation's object id */
+       LockInfoData rd_lockInfo;       /* lock manager's info for locking relation */
+       TupleDesc       rd_att;                 /* tuple descriptor */
        RuleLock   *rd_rules;           /* rewrite rules */
        IndexStrategy rd_istrat;
        RegProcedure *rd_support;
@@ -66,6 +87,7 @@ typedef struct RelationData
 
 typedef RelationData *Relation;
 
+
 /* ----------------
  *             RelationPtr is used in the executor to support index scans
  *             where we have to keep track of several index relations in an
@@ -74,7 +96,6 @@ typedef RelationData *Relation;
  */
 typedef Relation *RelationPtr;
 
-#define InvalidRelation ((Relation)NULL)
 
 /*
  * RelationIsValid
@@ -82,6 +103,8 @@ typedef Relation *RelationPtr;
  */
 #define RelationIsValid(relation) PointerIsValid(relation)
 
+#define InvalidRelation ((Relation) NULL)
+
 /*
  * RelationGetSystemPort
  *             Returns system port of a relation.
@@ -91,13 +114,6 @@ typedef Relation *RelationPtr;
  */
 #define RelationGetSystemPort(relation) ((relation)->rd_fd)
 
-/*
- * RelationGetLockInfo
- *             Returns the lock information structure in the reldesc
- *
- */
-#define RelationGetLockInfo(relation) ((relation)->lockInfo)
-
 /*
  * RelationHasReferenceCountZero
  *             True iff relation reference count is zero.
@@ -112,13 +128,13 @@ typedef Relation *RelationPtr;
  * RelationSetReferenceCount
  *             Sets relation reference count.
  */
-#define RelationSetReferenceCount(relation,count) ((relation)->rd_refcnt = count)
+#define RelationSetReferenceCount(relation,count) ((relation)->rd_refcnt = (count))
 
 /*
  * RelationIncrementReferenceCount
  *             Increments relation reference count.
  */
-#define RelationIncrementReferenceCount(relation) ((relation)->rd_refcnt += 1);
+#define RelationIncrementReferenceCount(relation) ((relation)->rd_refcnt += 1)
 
 /*
  * RelationDecrementReferenceCount
@@ -135,7 +151,6 @@ typedef Relation *RelationPtr;
  */
 #define RelationGetForm(relation) ((relation)->rd_rel)
 
-
 /*
  * RelationGetRelid
  *
@@ -151,7 +166,6 @@ typedef Relation *RelationPtr;
  */
 #define RelationGetFile(relation) ((relation)->rd_fd)
 
-
 /*
  * RelationGetRelationName
  *
@@ -160,21 +174,19 @@ typedef Relation *RelationPtr;
 #define RelationGetRelationName(relation) (&(relation)->rd_rel->relname)
 
 /*
- * RelationGetRelationName
+ * RelationGetNumberOfAttributes
  *
- *       Returns the number of attributes.
+ *       Returns the number of attributes.
  */
 #define RelationGetNumberOfAttributes(relation) ((relation)->rd_rel->relnatts)
 
 /*
  * RelationGetDescr
  *             Returns tuple descriptor for a relation.
- *
- * Note:
- *             Assumes relation descriptor is valid.
  */
 #define RelationGetDescr(relation) ((relation)->rd_att)
 
+
 extern IndexStrategy RelationGetIndexStrategy(Relation relation);
 
 extern void RelationSetIndexSupport(Relation relation, IndexStrategy strategy,