aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/gist/gist.c48
-rw-r--r--src/backend/access/hash/hash.c17
-rw-r--r--src/backend/access/heap/heapam.c91
-rw-r--r--src/backend/access/index/indexam.c49
-rw-r--r--src/backend/access/index/istrat.c19
-rw-r--r--src/backend/access/nbtree/nbtree.c17
-rw-r--r--src/backend/access/rtree/rtree.c46
-rw-r--r--src/backend/access/transam/transam.c9
-rw-r--r--src/backend/access/transam/varsup.c4
-rw-r--r--src/backend/bootstrap/bootstrap.c29
-rw-r--r--src/backend/catalog/aclchk.c69
-rw-r--r--src/backend/catalog/heap.c132
-rw-r--r--src/backend/catalog/index.c116
-rw-r--r--src/backend/catalog/indexing.c6
-rw-r--r--src/backend/catalog/pg_aggregate.c34
-rw-r--r--src/backend/catalog/pg_operator.c21
-rw-r--r--src/backend/catalog/pg_proc.c6
-rw-r--r--src/backend/catalog/pg_type.c31
-rw-r--r--src/backend/commands/async.c93
-rw-r--r--src/backend/commands/cluster.c56
-rw-r--r--src/backend/commands/command.c63
-rw-r--r--src/backend/commands/copy.c31
-rw-r--r--src/backend/commands/creatinh.c34
-rw-r--r--src/backend/commands/dbcommands.c27
-rw-r--r--src/backend/commands/explain.c7
-rw-r--r--src/backend/commands/indexcmds.c8
-rw-r--r--src/backend/commands/proclang.c12
-rw-r--r--src/backend/commands/remove.c52
-rw-r--r--src/backend/commands/rename.c48
-rw-r--r--src/backend/commands/sequence.c28
-rw-r--r--src/backend/commands/trigger.c55
-rw-r--r--src/backend/commands/user.c143
-rw-r--r--src/backend/commands/vacuum.c44
-rw-r--r--src/backend/executor/execAmi.c60
-rw-r--r--src/backend/executor/execMain.c19
-rw-r--r--src/backend/executor/execUtils.c10
-rw-r--r--src/backend/executor/nodeAppend.c6
-rw-r--r--src/backend/optimizer/path/indxpath.c16
-rw-r--r--src/backend/optimizer/plan/planner.c44
-rw-r--r--src/backend/optimizer/util/plancat.c22
-rw-r--r--src/backend/parser/analyze.c8
-rw-r--r--src/backend/parser/parse_clause.c8
-rw-r--r--src/backend/parser/parse_func.c47
-rw-r--r--src/backend/parser/parse_oper.c15
-rw-r--r--src/backend/parser/parse_relation.c18
-rw-r--r--src/backend/rewrite/locks.c6
-rw-r--r--src/backend/rewrite/rewriteDefine.c20
-rw-r--r--src/backend/rewrite/rewriteHandler.c17
-rw-r--r--src/backend/rewrite/rewriteRemove.c12
-rw-r--r--src/backend/rewrite/rewriteSupport.c32
-rw-r--r--src/backend/storage/buffer/bufmgr.c13
-rw-r--r--src/backend/storage/buffer/localbuf.c8
-rw-r--r--src/backend/storage/large_object/inv_api.c28
-rw-r--r--src/backend/storage/lmgr/lmgr.c82
-rw-r--r--src/backend/storage/lmgr/lock.c6
-rw-r--r--src/backend/tcop/utility.c33
-rw-r--r--src/backend/utils/adt/not_in.c13
-rw-r--r--src/backend/utils/adt/regproc.c33
-rw-r--r--src/backend/utils/adt/selfuncs.c8
-rw-r--r--src/backend/utils/adt/sets.c8
-rw-r--r--src/backend/utils/cache/catcache.c21
-rw-r--r--src/backend/utils/cache/relcache.c90
-rw-r--r--src/backend/utils/cache/syscache.c19
-rw-r--r--src/backend/utils/fmgr/dfmgr.c31
-rw-r--r--src/backend/utils/misc/database.c10
-rw-r--r--src/include/access/heapam.h9
-rw-r--r--src/include/storage/buf_internals.h6
-rw-r--r--src/include/storage/lmgr.h22
-rw-r--r--src/include/utils/rel.h56
69 files changed, 1093 insertions, 1208 deletions
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index 32111347423..0535fd6278d 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -6,7 +6,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.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 */
diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c
index 1130367b65d..6e729008e85 100644
--- a/src/backend/access/hash/hash.c
+++ b/src/backend/access/hash/hash.c
@@ -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);
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index d8dc24c41f0..092a23cc0ec 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -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,15 +619,9 @@ 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
* ----------------
@@ -598,6 +629,20 @@ heap_beginscan(Relation 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
* ----------------
*/
@@ -684,14 +729,18 @@ 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);
}
/* ----------------
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 869e5e1e690..6ad242c0c39 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -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
@@ -129,26 +129,49 @@
* 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);
}
/* ----------------
diff --git a/src/backend/access/index/istrat.c b/src/backend/access/index/istrat.c
index 1cdaadbc0c3..cab6e584609 100644
--- a/src/backend/access/index/istrat.c
+++ b/src/backend/access/index/istrat.c
@@ -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);
}
/* ----------------
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index c97273f10f0..11f527fc3ba 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -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);
diff --git a/src/backend/access/rtree/rtree.c b/src/backend/access/rtree/rtree.c
index 37da716df1d..133bbdbc032 100644
--- a/src/backend/access/rtree/rtree.c
+++ b/src/backend/access/rtree/rtree.c
@@ -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 */
diff --git a/src/backend/access/transam/transam.c b/src/backend/access/transam/transam.c
index 1f44fb357ac..b26243b4257 100644
--- a/src/backend/access/transam/transam.c
+++ b/src/backend/access/transam/transam.c
@@ -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
diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c
index 135912e97de..989b506bb7f 100644
--- a/src/backend/access/transam/varsup.c
+++ b/src/backend/access/transam/varsup.c
@@ -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.
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 8db37d0a081..18d9567ab89 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -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? */
}
}
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 186ecd07f32..33a589ec88b 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -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)
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 561cb21a418..644f03eba87 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -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;
}
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index c90c27fd5de..912996fb1fc 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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;
}
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index 9007258f2e8..75799e55570 100644
--- a/src/backend/catalog/indexing.c
+++ b/src/backend/catalog/indexing.c
@@ -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))
{
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index c8f02287cb8..0f2b98da906 100644
--- a/src/backend/catalog/pg_aggregate.c
+++ b/src/backend/catalog/pg_aggregate.c
@@ -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),
diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c
index 8cab520f520..53b250fe3fa 100644
--- a/src/backend/catalog/pg_operator.c
+++ b/src/backend/catalog/pg_operator.c
@@ -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);
}
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index f0a10cf8f89..b71f36e6618 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -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;
}
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index a219767858c..91c7cd995ba 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -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);
}
/*
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index ebdd045ce4f..f8196f86ab3 100644
--- a/src/backend/commands/async.c
+++ b/src/backend/commands/async.c
@@ -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 $
*
*-------------------------------------------------------------------------
*/
@@ -51,16 +51,9 @@
* 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();
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index 6f99a920f5a..d578fc263f0 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -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);
}
diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c
index 7fe62cf1246..8872bcdfac7 100644
--- a/src/backend/commands/command.c
+++ b/src/backend/commands/command.c
@@ -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;
@@ -311,6 +312,14 @@ PerformAddAttribute(char *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
*/
if (colDef->is_not_null)
@@ -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 */
}
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 35f3d6da0b3..493d2a170e1 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -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)
diff --git a/src/backend/commands/creatinh.c b/src/backend/commands/creatinh.c
index b93a40e7ba3..c1069dd41e6 100644
--- a/src/backend/commands/creatinh.c
+++ b/src/backend/commands/creatinh.c
@@ -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);
}
/*
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index b779715fe8e..24eb5b531d3 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -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.
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 3b1da18783d..11e5c394239 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -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)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 31d3419bee6..113854311d6 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -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 */
}
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 21fde2af579..b2fc76f090b 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -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);
}
diff --git a/src/backend/commands/remove.c b/src/backend/commands/remove.c
index af20c79f17d..a73964cb02c 100644
--- a/src/backend/commands/remove.c
+++ b/src/backend/commands/remove.c
@@ -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);
}
diff --git a/src/backend/commands/rename.c b/src/backend/commands/rename.c
index 1a93027b4a3..3a822bd4e49 100644
--- a/src/backend/commands/rename.c
+++ b/src/backend/commands/rename.c
@@ -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,
@@ -72,6 +73,14 @@ renameatt(char *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
* 'relname').
@@ -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);
}
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index b7f959cd65e..be47d32f9f9 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -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;
-
}
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 55f67711c77..aa7a0b56c1d 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -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;
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 1b0d972839e..c05b6da5856 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -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();
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 55ec864fca5..3027763b468 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -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 */
diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c
index 40a94fd02c8..9c1b7b8bb41 100644
--- a/src/backend/executor/execAmi.c
+++ b/src/backend/executor/execAmi.c
@@ -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;
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 48c0a885f3c..97dffe548f7 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -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);
}
/* ----------------------------------------------------------------
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 4bacf3f7bdb..197995c3462 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -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)
diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c
index 19a1e53b69f..bd515d51f97 100644
--- a/src/backend/executor/nodeAppend.c
+++ b/src/backend/executor/nodeAppend.c
@@ -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);
}
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 68fb4eda07e..3964d5d5bbe 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -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
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index a22d3ed43ae..32a5bb52cda 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -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);
}
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 9ca188bce62..ef120f8d2fe 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -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;
}
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 2c4d1c7a7e8..276d28b3aa1 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -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);
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index 234987fb5f0..bae53ebbd87 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -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 */
}
/*
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 19a287d99e8..15e63f7c98f 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -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;
}
diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
index 8f82e58517d..5a5c8709969 100644
--- a/src/backend/parser/parse_oper.c
+++ b/src/backend/parser/parse_oper.c
@@ -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() */
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 79b08635f02..af18087aa58 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -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;
}
diff --git a/src/backend/rewrite/locks.c b/src/backend/rewrite/locks.c
index c478a7facee..ef96b85210c 100644
--- a/src/backend/rewrite/locks.c
+++ b/src/backend/rewrite/locks.c
@@ -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));
/*
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index b118bf8de5d..c9be17151a9 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -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,
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index 0fa7fd72d43..b13cb5e3ed1 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -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);
}
}
diff --git a/src/backend/rewrite/rewriteRemove.c b/src/backend/rewrite/rewriteRemove.c
index 14ceeead848..50e6c62c027 100644
--- a/src/backend/rewrite/rewriteRemove.c
+++ b/src/backend/rewrite/rewriteRemove.c
@@ -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);
}
diff --git a/src/backend/rewrite/rewriteSupport.c b/src/backend/rewrite/rewriteSupport.c
index c8d9d023efe..c089be56d31 100644
--- a/src/backend/rewrite/rewriteSupport.c
+++ b/src/backend/rewrite/rewriteSupport.c
@@ -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);
}
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index de0d803efe2..b435dd53cac 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -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);
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index a6a2d456b26..e003595beda 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -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;
diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c
index 6b8765bb81c..f59e99d7fbe 100644
--- a/src/backend/storage/large_object/inv_api.c
+++ b/src/backend/storage/large_object/inv_api.c
@@ -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);
}
diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c
index 839533952b5..2aaaf69e83e 100644
--- a/src/backend/storage/lmgr/lmgr.c
+++ b/src/backend/storage/lmgr/lmgr.c
@@ -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 $
*
*-------------------------------------------------------------------------
*/
@@ -20,11 +20,12 @@
#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;
}
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 427cc749c84..3f5322c9f08 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -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);
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 8c1ac556149..29b4fb527c6 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -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));
diff --git a/src/backend/utils/adt/not_in.c b/src/backend/utils/adt/not_in.c
index 2ef45f63e42..1a851cf7e5f 100644
--- a/src/backend/utils/adt/not_in.c
+++ b/src/backend/utils/adt/not_in.c
@@ -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;
}
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index 754eea3a96e..b3179e864c1 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -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;
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 1b2d58c075e..e14e5375553 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -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;
}
diff --git a/src/backend/utils/adt/sets.c b/src/backend/utils/adt/sets.c
index 05bc16b92af..46dbca9d698 100644
--- a/src/backend/utils/adt/sets.c
+++ b/src/backend/utils/adt/sets.c
@@ -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;
}
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index f6ef0fecac2..22d933bb37a 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -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);
}
/* ----------------
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index db685e751eb..afba41db108 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -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
@@ -1049,13 +1039,17 @@ 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);
}
}
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index c9c7770f8cc..204f13ffab9 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -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;
}
diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c
index d48d8b8840a..dcf2814171b 100644
--- a/src/backend/utils/fmgr/dfmgr.c
+++ b/src/backend/utils/fmgr/dfmgr.c
@@ -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;
diff --git a/src/backend/utils/misc/database.c b/src/backend/utils/misc/database.c
index 39270f35c0c..321ab943aea 100644
--- a/src/backend/utils/misc/database.c
+++ b/src/backend/utils/misc/database.c
@@ -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;
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 8c1461122fc..b6dccc33fa8 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -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);
diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h
index 98d8be3369d..b98f0fb820f 100644
--- a/src/include/storage/buf_internals.h
+++ b/src/include/storage/buf_internals.h
@@ -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)))
diff --git a/src/include/storage/lmgr.h b/src/include/storage/lmgr.h
index 8903af8ec6b..302bedb6771 100644
--- a/src/include/storage/lmgr.h
+++ b/src/include/storage/lmgr.h
@@ -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 $
*
*-------------------------------------------------------------------------
*/
@@ -16,6 +16,11 @@
#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 */
@@ -27,21 +32,6 @@
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);
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index c95f51e89d1..f2789b39e09 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -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 $
*
*-------------------------------------------------------------------------
*/
@@ -20,6 +20,26 @@
#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.
@@ -92,13 +115,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 a 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,