Mega-commit to make heap_open/heap_openr/heap_close take an

additional argument specifying the kind of lock to acquire/release (or
'NoLock' to do no lock processing).  Ensure that all relations are locked
with some appropriate lock level before being examined --- this ensures
that relevant shared-inval messages have been processed and should prevent
problems caused by concurrent VACUUM.  Fix several bugs having to do with
mismatched increment/decrement of relation ref count and mismatched
heap_open/close (which amounts to the same thing).  A bogus ref count on
a relation doesn't matter much *unless* a SI Inval message happens to
arrive at the wrong time, which is probably why we got away with this
sloppiness for so long.  Repair missing grab of AccessExclusiveLock in
DROP TABLE, ALTER/RENAME TABLE, etc, as noted by Hiroshi.
Recommend 'make clean all' after pulling this update; I modified the
Relation struct layout slightly.
Will post further discussion to pghackers list shortly.
This commit is contained in:
Tom Lane 1999-09-18 19:08:25 +00:00
parent 6c86fd5ba4
commit bd272cace6
70 changed files with 1094 additions and 1215 deletions

View File

@ -89,9 +89,8 @@ active_listeners(text *relname)
int ourpid = getpid(); int ourpid = getpid();
char listen_name[NAMEDATALEN]; char listen_name[NAMEDATALEN];
lRel = heap_openr(ListenerRelationName); lRel = heap_openr(ListenerRelationName, AccessShareLock);
tdesc = RelationGetDescr(lRel); tdesc = RelationGetDescr(lRel);
LockRelation(lRel, AccessShareLock);
if (relname && (VARSIZE(relname) > VARHDRSZ)) { if (relname && (VARSIZE(relname) > VARHDRSZ)) {
len = MIN(VARSIZE(relname)-VARHDRSZ, NAMEDATALEN-1); len = MIN(VARSIZE(relname)-VARHDRSZ, NAMEDATALEN-1);
@ -110,19 +109,14 @@ active_listeners(text *relname)
{ {
d = heap_getattr(lTuple, Anum_pg_listener_pid, tdesc, &isnull); d = heap_getattr(lTuple, Anum_pg_listener_pid, tdesc, &isnull);
pid = DatumGetInt32(d); pid = DatumGetInt32(d);
#ifdef HAVE_KILL
if ((pid == ourpid) || (kill(pid, SIGTSTP) == 0)) { if ((pid == ourpid) || (kill(pid, SIGTSTP) == 0)) {
/* elog(NOTICE, "%d ok", pid); */ /* elog(NOTICE, "%d ok", pid); */
count++; count++;
} }
#else
count++;
#endif
} }
heap_endscan(sRel); heap_endscan(sRel);
UnlockRelation(lRel, AccessShareLock); heap_close(lRel, AccessShareLock);
heap_close(lRel);
return count; return count;
} }

View File

@ -6,7 +6,7 @@
* *
* *
* IDENTIFICATION * 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/index.h"
#include "catalog/pg_index.h" #include "catalog/pg_index.h"
#include "executor/executor.h" #include "executor/executor.h"
#include "miscadmin.h"
#include "utils/syscache.h" #include "utils/syscache.h"
@ -88,8 +89,6 @@ gistbuild(Relation heap,
TupleTableSlot *slot; TupleTableSlot *slot;
#endif #endif
Oid hrelid,
irelid;
Node *pred, Node *pred,
*oldPred; *oldPred;
GISTSTATE giststate; GISTSTATE giststate;
@ -271,28 +270,31 @@ gistbuild(Relation heap,
} }
/* /*
* Since we just inted the tuples in the heap, we update its stats in * Since we just counted the tuples in the heap, we update its stats
* pg_relation to guarantee that the planner takes advantage of the * in pg_class to guarantee that the planner takes advantage of the
* index we just created. UpdateStats() does a * index we just created. But, only update statistics during
* CommandinterIncrement(), which flushes changed entries from the * normal index definitions, not for indices on system catalogs
* system relcache. The act of constructing an index changes these * created during bootstrap processing. We must close the relations
* heap and index tuples in the system catalogs, so they need to be * before updating statistics to guarantee that the relcache entries
* flushed. We close them to guarantee that they will be. * 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);
index_close(index);
UpdateStats(hrelid, nh, true);
UpdateStats(irelid, ni, false);
if (oldPred != NULL)
{ {
if (ni == nh) Oid hrelid = RelationGetRelid(heap);
pred = NULL; Oid irelid = RelationGetRelid(index);
UpdateIndexPredicate(irelid, oldPred, pred);
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 */ /* be tidy */

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* This file contains only the public interface routines. * This file contains only the public interface routines.
@ -66,8 +66,6 @@ hashbuild(Relation heap,
TupleTableSlot *slot; TupleTableSlot *slot;
#endif #endif
Oid hrelid,
irelid;
Node *pred, Node *pred,
*oldPred; *oldPred;
@ -232,17 +230,20 @@ hashbuild(Relation heap,
/* /*
* Since we just counted the tuples in the heap, we update its stats * 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 * 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 * normal index definitions, not for indices on system catalogs
* created during bootstrap processing. We must close the relations * 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(). * 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 (IsNormalProcessingMode())
{ {
hrelid = RelationGetRelid(heap); Oid hrelid = RelationGetRelid(heap);
irelid = RelationGetRelid(index); Oid irelid = RelationGetRelid(index);
heap_close(heap);
heap_close(heap, NoLock);
index_close(index); index_close(index);
UpdateStats(hrelid, nhtups, true); UpdateStats(hrelid, nhtups, true);
UpdateStats(irelid, nitups, false); UpdateStats(irelid, nitups, false);

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 * INTERFACE ROUTINES
@ -486,15 +486,20 @@ heapgettup(Relation relation,
/* ---------------- /* ----------------
* heap_open - open a heap relation by relationId * heap_open - open a heap relation by relationId
* *
* presently the relcache routines do all the work we need * If lockmode is "NoLock", no lock is obtained on the relation,
* to open/close heap relations. * 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 Relation
heap_open(Oid relationId) heap_open(Oid relationId, LOCKMODE lockmode)
{ {
Relation r; Relation r;
Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
/* ---------------- /* ----------------
* increment access statistics * increment access statistics
* ---------------- * ----------------
@ -502,26 +507,41 @@ heap_open(Oid relationId)
IncrHeapAccessStat(local_open); IncrHeapAccessStat(local_open);
IncrHeapAccessStat(global_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) if (RelationIsValid(r) && r->rd_rel->relkind == RELKIND_INDEX)
elog(ERROR, "%s is an index relation", r->rd_rel->relname.data); 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; return r;
} }
/* ---------------- /* ----------------
* heap_openr - open a heap relation by name * heap_openr - open a heap relation by name
* *
* presently the relcache routines do all the work we need * If lockmode is "NoLock", no lock is obtained on the relation,
* to open/close heap relations. * 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 Relation
heap_openr(char *relationName) heap_openr(char *relationName, LOCKMODE lockmode)
{ {
Relation r; Relation r;
Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
/* ---------------- /* ----------------
* increment access statistics * increment access statistics
* ---------------- * ----------------
@ -529,24 +549,37 @@ heap_openr(char *relationName)
IncrHeapAccessStat(local_openr); IncrHeapAccessStat(local_openr);
IncrHeapAccessStat(global_openr); IncrHeapAccessStat(global_openr);
/* The relcache does all the real work... */
r = RelationNameGetRelation(relationName); r = RelationNameGetRelation(relationName);
/* Under no circumstances will we return an index as a relation. */
if (RelationIsValid(r) && r->rd_rel->relkind == RELKIND_INDEX) if (RelationIsValid(r) && r->rd_rel->relkind == RELKIND_INDEX)
elog(ERROR, "%s is an index relation", r->rd_rel->relname.data); 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; return r;
} }
/* ---------------- /* ----------------
* heap_close - close a heap relation * heap_close - close a heap relation
* *
* presently the relcache routines do all the work we need * If lockmode is not "NoLock", we first release the specified lock.
* to open/close heap relations. * 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 void
heap_close(Relation relation) heap_close(Relation relation, LOCKMODE lockmode)
{ {
Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
/* ---------------- /* ----------------
* increment access statistics * increment access statistics
* ---------------- * ----------------
@ -554,6 +587,10 @@ heap_close(Relation relation)
IncrHeapAccessStat(local_close); IncrHeapAccessStat(local_close);
IncrHeapAccessStat(global_close); IncrHeapAccessStat(global_close);
if (lockmode != NoLock)
UnlockRelation(relation, lockmode);
/* The relcache does the real work... */
RelationClose(relation); RelationClose(relation);
} }
@ -582,21 +619,29 @@ heap_beginscan(Relation relation,
* sanity checks * sanity checks
* ---------------- * ----------------
*/ */
if (RelationIsValid(relation) == false) if (! RelationIsValid(relation))
elog(ERROR, "heap_beginscan: !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 * increment relation ref count while scanning relation
* ---------------- * ----------------
*/ */
RelationIncrementReferenceCount(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 * allocate and initialize scan descriptor
* ---------------- * ----------------
@ -683,15 +728,19 @@ heap_endscan(HeapScanDesc scan)
*/ */
unpinscan(scan); unpinscan(scan);
/* ----------------
* Release AccessShareLock acquired by heap_beginscan()
* ----------------
*/
UnlockRelation(scan->rs_rd, AccessShareLock);
/* ---------------- /* ----------------
* decrement relation reference count and free scan descriptor storage * decrement relation reference count and free scan descriptor storage
* ---------------- * ----------------
*/ */
RelationDecrementReferenceCount(scan->rs_rd); RelationDecrementReferenceCount(scan->rs_rd);
UnlockRelation(scan->rs_rd, AccessShareLock); pfree(scan);
pfree(scan); /* XXX */
} }
/* ---------------- /* ----------------

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 * INTERFACE ROUTINES
* index_open - open an index relation by relationId * index_open - open an index relation by relationId
@ -129,26 +129,49 @@
* index_open - open an index relation by relationId * index_open - open an index relation by relationId
* *
* presently the relcache routines do all the work we need * 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 Relation
index_open(Oid relationId) 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 * index_openr - open a index relation by name
* *
* presently the relcache routines do all the work we need * As above, but lookup by name instead of OID.
* to open/close index relations.
* ---------------- * ----------------
*/ */
Relation Relation
index_openr(char *relationName) 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; RELATION_CHECKS;
GET_REL_PROCEDURE(beginscan, ambeginscan); 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); LockRelation(relation, AccessShareLock);
scandesc = (IndexScanDesc) scandesc = (IndexScanDesc)
@ -260,7 +293,11 @@ index_endscan(IndexScanDesc scan)
fmgr(procedure, scan); fmgr(procedure, scan);
/* Release lock and refcount acquired by index_beginscan */
UnlockRelation(scan->relation, AccessShareLock); UnlockRelation(scan->relation, AccessShareLock);
RelationDecrementReferenceCount(scan->relation);
} }
/* ---------------- /* ----------------

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, F_OIDEQ,
ObjectIdGetDatum(indexObjectId)); ObjectIdGetDatum(indexObjectId));
relation = heap_openr(IndexRelationName); relation = heap_openr(IndexRelationName, AccessShareLock);
scan = heap_beginscan(relation, false, SnapshotNow, 1, entry); scan = heap_beginscan(relation, false, SnapshotNow, 1, entry);
tuple = heap_getnext(scan, 0); tuple = heap_getnext(scan, 0);
} }
@ -591,7 +591,7 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
if (IsBootstrapProcessingMode()) if (IsBootstrapProcessingMode())
{ {
heap_endscan(scan); heap_endscan(scan);
heap_close(relation); heap_close(relation, AccessShareLock);
} }
/* if support routines exist for this access method, load them */ /* 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, ScanKeyEntryInitialize(&entry[1], 0, Anum_pg_amproc_amopclaid,
F_OIDEQ, 0); F_OIDEQ, 0);
relation = heap_openr(AccessMethodProcedureRelationName); relation = heap_openr(AccessMethodProcedureRelationName,
AccessShareLock);
for (attributeNumber = 1; attributeNumber <= maxAttributeNumber; for (attributeNumber = 1; attributeNumber <= maxAttributeNumber;
attributeNumber++) attributeNumber++)
@ -631,7 +632,7 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
heap_endscan(scan); heap_endscan(scan);
} }
heap_close(relation); heap_close(relation, AccessShareLock);
} }
ScanKeyEntryInitialize(&entry[0], 0, ScanKeyEntryInitialize(&entry[0], 0,
@ -643,8 +644,8 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
Anum_pg_amop_amopclaid, Anum_pg_amop_amopclaid,
F_OIDEQ, 0); F_OIDEQ, 0);
relation = heap_openr(AccessMethodOperatorRelationName); relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock);
operatorRelation = heap_openr(OperatorRelationName); operatorRelation = heap_openr(OperatorRelationName, AccessShareLock);
for (attributeNumber = maxAttributeNumber; attributeNumber > 0; for (attributeNumber = maxAttributeNumber; attributeNumber > 0;
attributeNumber--) attributeNumber--)
@ -676,8 +677,8 @@ IndexSupportInitialize(IndexStrategy indexStrategy,
heap_endscan(scan); heap_endscan(scan);
} }
heap_close(operatorRelation); heap_close(operatorRelation, AccessShareLock);
heap_close(relation); heap_close(relation, AccessShareLock);
} }
/* ---------------- /* ----------------

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* This file contains only the public interface routines. * This file contains only the public interface routines.
@ -74,8 +74,6 @@ btbuild(Relation heap,
TupleTableSlot *slot = (TupleTableSlot *) NULL; TupleTableSlot *slot = (TupleTableSlot *) NULL;
#endif #endif
Oid hrelid,
irelid;
Node *pred, Node *pred,
*oldPred; *oldPred;
void *spool = (void *) NULL; void *spool = (void *) NULL;
@ -301,17 +299,20 @@ btbuild(Relation heap,
/* /*
* Since we just counted the tuples in the heap, we update its stats * 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 * 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 * normal index definitions, not for indices on system catalogs
* created during bootstrap processing. We must close the relations * 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(). * 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 (IsNormalProcessingMode())
{ {
hrelid = RelationGetRelid(heap); Oid hrelid = RelationGetRelid(heap);
irelid = RelationGetRelid(index); Oid irelid = RelationGetRelid(index);
heap_close(heap);
heap_close(heap, NoLock);
index_close(index); index_close(index);
UpdateStats(hrelid, nhtups, true); UpdateStats(hrelid, nhtups, true);
UpdateStats(irelid, nitups, false); UpdateStats(irelid, nitups, false);

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 "access/rtree.h"
#include "catalog/index.h" #include "catalog/index.h"
#include "executor/executor.h" #include "executor/executor.h"
#include "miscadmin.h"
#include "utils/geo_decls.h" #include "utils/geo_decls.h"
@ -89,8 +90,6 @@ rtbuild(Relation heap,
TupleTableSlot *slot; TupleTableSlot *slot;
#endif #endif
Oid hrelid,
irelid;
Node *pred, Node *pred,
*oldPred; *oldPred;
RTSTATE rtState; RTSTATE rtState;
@ -248,27 +247,30 @@ rtbuild(Relation heap,
/* /*
* Since we just counted the tuples in the heap, we update its stats * 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 * in pg_class to guarantee that the planner takes advantage of the
* index we just created. UpdateStats() does a * index we just created. But, only update statistics during
* CommandCounterIncrement(), which flushes changed entries from the * normal index definitions, not for indices on system catalogs
* system relcache. The act of constructing an index changes these * created during bootstrap processing. We must close the relations
* heap and index tuples in the system catalogs, so they need to be * before updating statistics to guarantee that the relcache entries
* flushed. We close them to guarantee that they will be. * 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);
index_close(index);
UpdateStats(hrelid, nh, true);
UpdateStats(irelid, ni, false);
if (oldPred != NULL)
{ {
if (ni == nh) Oid hrelid = RelationGetRelid(heap);
pred = NULL; Oid irelid = RelationGetRelid(index);
UpdateIndexPredicate(irelid, oldPred, pred);
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 */ /* be tidy */

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* This file contains the high level access-method interface to the * 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) * (these are created by amiint so they are guaranteed to exist)
* ---------------- * ----------------
*/ */
logRelation = heap_openr(LogRelationName); logRelation = heap_openr(LogRelationName, NoLock);
VariableRelation = heap_openr(VariableRelationName); Assert(logRelation != NULL);
VariableRelation = heap_openr(VariableRelationName, NoLock);
Assert(VariableRelation != NULL);
/* ---------------- /* ----------------
* XXX TransactionLogUpdate requires that LogRelation * XXX TransactionLogUpdate requires that LogRelation
* is valid so we temporarily set it so we can initialize * is valid so we temporarily set it so we can initialize

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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)) if (!RelationIsValid(VariableRelation))
VariableRelation = heap_openr(VariableRelationName); VariableRelation = heap_openr(VariableRelationName, NoLock);
/* ---------------- /* ----------------
* get a new block of prefetched object ids. * get a new block of prefetched object ids.

View File

@ -7,7 +7,7 @@
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/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) if (Typ == (struct typmap **) NULL)
{ {
StartPortalAllocMode(DefaultAllocMode, 0); StartPortalAllocMode(DefaultAllocMode, 0);
rel = heap_openr(TypeRelationName); rel = heap_openr(TypeRelationName, NoLock);
Assert(rel);
scan = heap_beginscan(rel, 0, SnapshotNow, 0, (ScanKey) NULL); scan = heap_beginscan(rel, 0, SnapshotNow, 0, (ScanKey) NULL);
i = 0; i = 0;
while (HeapTupleIsValid(tup = heap_getnext(scan, 0))) while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
@ -416,7 +417,7 @@ boot_openrel(char *relname)
sizeof((*app)->am_typ)); sizeof((*app)->am_typ));
} }
heap_endscan(scan); heap_endscan(scan);
heap_close(rel); heap_close(rel, NoLock);
EndPortalAllocMode(); EndPortalAllocMode();
} }
@ -427,7 +428,7 @@ boot_openrel(char *relname)
printf("Amopen: relation %s. attrsize %d\n", relname ? relname : "(null)", printf("Amopen: relation %s. attrsize %d\n", relname ? relname : "(null)",
(int) ATTRIBUTE_TUPLE_SIZE); (int) ATTRIBUTE_TUPLE_SIZE);
reldesc = heap_openr(relname); reldesc = heap_openr(relname, NoLock);
Assert(reldesc); Assert(reldesc);
numattr = reldesc->rd_rel->relnatts; numattr = reldesc->rd_rel->relnatts;
for (i = 0; i < numattr; i++) for (i = 0; i < numattr; i++)
@ -490,7 +491,7 @@ closerel(char *name)
{ {
if (!Quiet) if (!Quiet)
printf("Amclose: relation %s.\n", relname ? relname : "(null)"); printf("Amclose: relation %s.\n", relname ? relname : "(null)");
heap_close(reldesc); heap_close(reldesc, NoLock);
reldesc = (Relation) NULL; reldesc = (Relation) NULL;
} }
} }
@ -737,7 +738,7 @@ cleanup()
proc_exit(1); proc_exit(1);
} }
if (reldesc != (Relation) NULL) if (reldesc != (Relation) NULL)
heap_close(reldesc); heap_close(reldesc, NoLock);
CommitTransactionCommand(); CommitTransactionCommand();
proc_exit(Warnings); proc_exit(Warnings);
} }
@ -775,7 +776,8 @@ gettype(char *type)
} }
if (DebugMode) if (DebugMode)
printf("bootstrap.c: External Type: %s\n", type); 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); scan = heap_beginscan(rel, 0, SnapshotNow, 0, (ScanKey) NULL);
i = 0; i = 0;
while (HeapTupleIsValid(tup = heap_getnext(scan, 0))) while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
@ -795,7 +797,7 @@ gettype(char *type)
sizeof((*app)->am_typ)); sizeof((*app)->am_typ));
} }
heap_endscan(scan); heap_endscan(scan);
heap_close(rel); heap_close(rel, NoLock);
return gettype(type); return gettype(type);
} }
elog(ERROR, "Error: unknown type '%s'.\n", type); elog(ERROR, "Error: unknown type '%s'.\n", type);
@ -1106,11 +1108,16 @@ build_indices()
for (; ILHead != (IndexList *) NULL; ILHead = ILHead->il_next) 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); ind = index_openr(ILHead->il_ind);
Assert(ind);
index_build(heap, ind, ILHead->il_natts, ILHead->il_attnos, index_build(heap, ind, ILHead->il_natts, ILHead->il_attnos,
ILHead->il_nparams, ILHead->il_params, ILHead->il_finfo, ILHead->il_nparams, ILHead->il_params, ILHead->il_finfo,
ILHead->il_predInfo); 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 * All of the rest of this routine is needed only because in
@ -1128,9 +1135,9 @@ build_indices()
* *
* -mer * -mer
*/ */
heap = heap_openr(ILHead->il_heap);
if (!BootstrapAlreadySeen(RelationGetRelid(heap))) if (!BootstrapAlreadySeen(RelationGetRelid(heap)))
UpdateStats(RelationGetRelid(heap), 0, true); UpdateStats(RelationGetRelid(heap), 0, true);
/* XXX Probably we ought to close the heap and index here? */
} }
} }

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* See acl.h. * 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 * We can't use the syscache here, since we need to do a heap_replace on
* the tuple we find. * the tuple we find.
*/ */
relation = heap_openr(RelationRelationName); relation = heap_openr(RelationRelationName, RowExclusiveLock);
if (!RelationIsValid(relation))
elog(ERROR, "ChangeAcl: could not open '%s'??",
RelationRelationName);
tuple = SearchSysCacheTuple(RELNAME, tuple = SearchSysCacheTuple(RELNAME,
PointerGetDatum(relname), PointerGetDatum(relname),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
{ {
heap_close(relation); heap_close(relation, RowExclusiveLock);
elog(ERROR, "ChangeAcl: class \"%s\" not found", elog(ERROR, "ChangeAcl: class \"%s\" not found",
relname); relname);
return;
} }
if (!heap_attisnull(tuple, Anum_pg_class_relacl)) if (!heap_attisnull(tuple, Anum_pg_class_relacl))
@ -164,7 +160,7 @@ ChangeAcl(char *relname,
CatalogIndexInsert(idescs, Num_pg_class_indices, relation, tuple); CatalogIndexInsert(idescs, Num_pg_class_indices, relation, tuple);
CatalogCloseIndices(Num_pg_class_indices, idescs); CatalogCloseIndices(Num_pg_class_indices, idescs);
heap_close(relation); heap_close(relation, RowExclusiveLock);
if (free_old_acl) if (free_old_acl)
pfree(old_acl); pfree(old_acl);
pfree(new_acl); pfree(new_acl);
@ -213,13 +209,7 @@ in_group(AclId uid, AclId gid)
AclId *aidp; AclId *aidp;
int32 found = 0; int32 found = 0;
relation = heap_openr(GroupRelationName); relation = heap_openr(GroupRelationName, RowExclusiveLock);
if (!RelationIsValid(relation))
{
elog(NOTICE, "in_group: could not open \"%s\"??",
GroupRelationName);
return 0;
}
tuple = SearchSysCacheTuple(GROSYSID, tuple = SearchSysCacheTuple(GROSYSID,
ObjectIdGetDatum(gid), ObjectIdGetDatum(gid),
0, 0, 0); 0, 0, 0);
@ -242,7 +232,7 @@ in_group(AclId uid, AclId gid)
} }
else else
elog(NOTICE, "in_group: group %d not found", gid); elog(NOTICE, "in_group: group %d not found", gid);
heap_close(relation); heap_close(relation, RowExclusiveLock);
return found; return found;
} }
@ -413,6 +403,7 @@ pg_aclcheck(char *relname, char *usename, AclMode mode)
} }
#ifndef ACLDEBUG #ifndef ACLDEBUG
relation = heap_openr(RelationRelationName, RowExclusiveLock);
tuple = SearchSysCacheTuple(RELNAME, tuple = SearchSysCacheTuple(RELNAME,
PointerGetDatum(relname), PointerGetDatum(relname),
0, 0, 0); 0, 0, 0);
@ -420,18 +411,15 @@ pg_aclcheck(char *relname, char *usename, AclMode mode)
{ {
elog(ERROR, "pg_aclcheck: class \"%s\" not found", elog(ERROR, "pg_aclcheck: class \"%s\" not found",
relname); relname);
/* an elog(ERROR) kills us, so no need to return anything. */
} }
if (!heap_attisnull(tuple, Anum_pg_class_relacl)) if (!heap_attisnull(tuple, Anum_pg_class_relacl))
{ {
relation = heap_openr(RelationRelationName);
tmp = (Acl *) heap_getattr(tuple, tmp = (Acl *) heap_getattr(tuple,
Anum_pg_class_relacl, Anum_pg_class_relacl,
RelationGetDescr(relation), RelationGetDescr(relation),
(bool *) NULL); (bool *) NULL);
acl = makeacl(ACL_NUM(tmp)); acl = makeacl(ACL_NUM(tmp));
memmove((char *) acl, (char *) tmp, ACL_SIZE(tmp)); memmove((char *) acl, (char *) tmp, ACL_SIZE(tmp));
heap_close(relation);
} }
else else
{ {
@ -442,42 +430,29 @@ pg_aclcheck(char *relname, char *usename, AclMode mode)
*/ */
int4 ownerId; int4 ownerId;
relation = heap_openr(RelationRelationName);
ownerId = (int4) heap_getattr(tuple, ownerId = (int4) heap_getattr(tuple,
Anum_pg_class_relowner, Anum_pg_class_relowner,
RelationGetDescr(relation), RelationGetDescr(relation),
(bool *) NULL); (bool *) NULL);
acl = aclownerdefault(relname, (AclId) ownerId); acl = aclownerdefault(relname, (AclId) ownerId);
heap_close(relation);
} }
heap_close(relation, RowExclusiveLock);
#else #else
{ /* This is why the syscache is great... */ relation = heap_openr(RelationRelationName, RowExclusiveLock);
static ScanKeyData relkey[1] = { tuple = SearchSysCacheTuple(RELNAME,
{0, Anum_pg_class_relname, F_NAMEEQ} PointerGetDatum(relname),
}; 0, 0, 0);
if (HeapTupleIsValid(tuple) &&
relation = heap_openr(RelationRelationName); !heap_attisnull(tuple, Anum_pg_class_relacl))
if (!RelationIsValid(relation)) {
{ tmp = (Acl *) heap_getattr(tuple,
elog(NOTICE, "pg_checkacl: could not open \"%-.*s\"??", Anum_pg_class_relacl,
RelationRelationName); RelationGetDescr(relation),
return ACLCHECK_NO_CLASS; (bool *) NULL);
} acl = makeacl(ACL_NUM(tmp));
tuple = SearchSysCacheTuple(RELNAME, memmove((char *) acl, (char *) tmp, ACL_SIZE(tmp));
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);
} }
heap_close(relation, RowExclusiveLock);
#endif #endif
result = aclcheck(relname, acl, id, (AclIdType) ACL_IDTYPE_UID, mode); result = aclcheck(relname, acl, id, (AclIdType) ACL_IDTYPE_UID, mode);
if (acl) if (acl)

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 * INTERFACE ROUTINES
@ -243,8 +243,6 @@ heap_create(char *relname,
/* ---------------- /* ----------------
* allocate a new relation descriptor. * allocate a new relation descriptor.
*
* XXX the length computation may be incorrect, handle elsewhere
* ---------------- * ----------------
*/ */
len = sizeof(RelationData); len = sizeof(RelationData);
@ -474,7 +472,7 @@ RelnameFindRelid(char *relname)
ScanKeyData key; ScanKeyData key;
HeapScanDesc pg_class_scan; 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 * 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_endscan(pg_class_scan);
heap_close(pg_class_desc); heap_close(pg_class_desc, AccessShareLock);
} }
return relid; return relid;
} }
@ -539,14 +537,12 @@ AddNewAttributeTuples(Oid new_rel_oid,
* open pg_attribute * open pg_attribute
* ---------------- * ----------------
*/ */
rel = heap_openr(AttributeRelationName); rel = heap_openr(AttributeRelationName, RowExclusiveLock);
/* ----------------- /* -----------------
* Check if we have any indices defined on pg_attribute. * Check if we have any indices defined on pg_attribute.
* ----------------- * -----------------
*/ */
Assert(rel);
Assert(rel->rd_rel);
hasindex = RelationGetForm(rel)->relhasindex; hasindex = RelationGetForm(rel)->relhasindex;
if (hasindex) if (hasindex)
CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs); CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
@ -607,7 +603,7 @@ AddNewAttributeTuples(Oid new_rel_oid,
dpp++; dpp++;
} }
heap_close(rel); heap_close(rel, RowExclusiveLock);
/* /*
* close pg_attribute indices * close pg_attribute indices
@ -829,7 +825,7 @@ heap_create_with_catalog(char *relname,
* now update the information in pg_class. * now update the information in pg_class.
* ---------------- * ----------------
*/ */
pg_class_desc = heap_openr(RelationRelationName); pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock);
AddNewRelationTuple(pg_class_desc, AddNewRelationTuple(pg_class_desc,
new_rel_desc, new_rel_desc,
@ -853,8 +849,8 @@ heap_create_with_catalog(char *relname,
* SOMEDAY: fill the STATISTIC relation properly. * SOMEDAY: fill the STATISTIC relation properly.
* ---------------- * ----------------
*/ */
heap_close(new_rel_desc); heap_close(new_rel_desc, NoLock); /* do not unlock till end of xact */
heap_close(pg_class_desc); heap_close(pg_class_desc, RowExclusiveLock);
return new_rel_oid; return new_rel_oid;
} }
@ -913,7 +909,7 @@ RelationRemoveInheritance(Relation relation)
* open pg_inherits * open pg_inherits
* ---------------- * ----------------
*/ */
catalogRelation = heap_openr(InheritsRelationName); catalogRelation = heap_openr(InheritsRelationName, RowExclusiveLock);
/* ---------------- /* ----------------
* form a scan key for the subclasses of this class * form a scan key for the subclasses of this class
@ -937,13 +933,15 @@ RelationRemoveInheritance(Relation relation)
tuple = heap_getnext(scan, 0); tuple = heap_getnext(scan, 0);
if (HeapTupleIsValid(tuple)) if (HeapTupleIsValid(tuple))
{ {
Oid subclass = ((Form_pg_inherits) GETSTRUCT(tuple))->inhrel;
heap_endscan(scan); heap_endscan(scan);
heap_close(catalogRelation); heap_close(catalogRelation, RowExclusiveLock);
elog(ERROR, "Relation '%u' inherits '%s'", elog(ERROR, "Relation '%u' inherits '%s'",
((Form_pg_inherits) GETSTRUCT(tuple))->inhrel, subclass, RelationGetRelationName(relation));
RelationGetRelationName(relation));
} }
heap_endscan(scan);
/* ---------------- /* ----------------
* If we get here, it means the relation has no subclasses * If we get here, it means the relation has no subclasses
@ -965,13 +963,14 @@ RelationRemoveInheritance(Relation relation)
} }
heap_endscan(scan); heap_endscan(scan);
heap_close(catalogRelation); heap_close(catalogRelation, RowExclusiveLock);
/* ---------------- /* ----------------
* now remove dead IPL tuples * now remove dead IPL tuples
* ---------------- * ----------------
*/ */
catalogRelation = heap_openr(InheritancePrecidenceListRelationName); catalogRelation = heap_openr(InheritancePrecidenceListRelationName,
RowExclusiveLock);
entry.sk_attno = Anum_pg_ipl_iplrel; entry.sk_attno = Anum_pg_ipl_iplrel;
@ -985,7 +984,7 @@ RelationRemoveInheritance(Relation relation)
heap_delete(catalogRelation, &tuple->t_self, NULL); heap_delete(catalogRelation, &tuple->t_self, NULL);
heap_endscan(scan); heap_endscan(scan);
heap_close(catalogRelation); heap_close(catalogRelation, RowExclusiveLock);
} }
/* -------------------------------- /* --------------------------------
@ -1001,7 +1000,7 @@ RelationRemoveIndexes(Relation relation)
HeapScanDesc scan; HeapScanDesc scan;
ScanKeyData entry; ScanKeyData entry;
indexRelation = heap_openr(IndexRelationName); indexRelation = heap_openr(IndexRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_index_indrelid, ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_index_indrelid,
F_OIDEQ, F_OIDEQ,
@ -1017,7 +1016,7 @@ RelationRemoveIndexes(Relation relation)
index_destroy(((Form_pg_index) GETSTRUCT(tuple))->indexrelid); index_destroy(((Form_pg_index) GETSTRUCT(tuple))->indexrelid);
heap_endscan(scan); heap_endscan(scan);
heap_close(indexRelation); heap_close(indexRelation, RowExclusiveLock);
} }
/* -------------------------------- /* --------------------------------
@ -1035,14 +1034,14 @@ DeleteRelationTuple(Relation rel)
* open pg_class * open pg_class
* ---------------- * ----------------
*/ */
pg_class_desc = heap_openr(RelationRelationName); pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock);
tup = SearchSysCacheTupleCopy(RELOID, tup = SearchSysCacheTupleCopy(RELOID,
ObjectIdGetDatum(rel->rd_att->attrs[0]->attrelid), ObjectIdGetDatum(rel->rd_att->attrs[0]->attrelid),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
{ {
heap_close(pg_class_desc); heap_close(pg_class_desc, RowExclusiveLock);
elog(ERROR, "Relation '%s' does not exist", elog(ERROR, "Relation '%s' does not exist",
&rel->rd_rel->relname); &rel->rd_rel->relname);
} }
@ -1054,7 +1053,7 @@ DeleteRelationTuple(Relation rel)
heap_delete(pg_class_desc, &tup->t_self, NULL); heap_delete(pg_class_desc, &tup->t_self, NULL);
pfree(tup); pfree(tup);
heap_close(pg_class_desc); heap_close(pg_class_desc, RowExclusiveLock);
} }
/* -------------------------------- /* --------------------------------
@ -1073,13 +1072,7 @@ DeleteAttributeTuples(Relation rel)
* open pg_attribute * open pg_attribute
* ---------------- * ----------------
*/ */
pg_attribute_desc = heap_openr(AttributeRelationName); pg_attribute_desc = heap_openr(AttributeRelationName, RowExclusiveLock);
/* -----------------
* Get a write lock _before_ getting the read lock in the scan
* ----------------
*/
LockRelation(pg_attribute_desc, AccessExclusiveLock);
for (attnum = FirstLowInvalidHeapAttributeNumber + 1; for (attnum = FirstLowInvalidHeapAttributeNumber + 1;
attnum <= rel->rd_att->natts; attnum <= rel->rd_att->natts;
@ -1095,12 +1088,7 @@ DeleteAttributeTuples(Relation rel)
} }
} }
/* ---------------- heap_close(pg_attribute_desc, RowExclusiveLock);
* Release the write lock
* ----------------
*/
UnlockRelation(pg_attribute_desc, AccessExclusiveLock);
heap_close(pg_attribute_desc);
} }
/* -------------------------------- /* --------------------------------
@ -1129,7 +1117,7 @@ DeleteTypeTuple(Relation rel)
* open pg_type * 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 * create a scan key to locate the type tuple corresponding
@ -1157,7 +1145,7 @@ DeleteTypeTuple(Relation rel)
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
{ {
heap_endscan(pg_type_scan); heap_endscan(pg_type_scan);
heap_close(pg_type_desc); heap_close(pg_type_desc, RowExclusiveLock);
elog(ERROR, "DeleteTypeTuple: %s type nonexistent", elog(ERROR, "DeleteTypeTuple: %s type nonexistent",
&rel->rd_rel->relname); &rel->rd_rel->relname);
} }
@ -1171,7 +1159,7 @@ DeleteTypeTuple(Relation rel)
*/ */
typoid = tup->t_data->t_oid; typoid = tup->t_data->t_oid;
pg_attribute_desc = heap_openr(AttributeRelationName); pg_attribute_desc = heap_openr(AttributeRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&attkey, ScanKeyEntryInitialize(&attkey,
0, 0,
@ -1197,16 +1185,16 @@ DeleteTypeTuple(Relation rel)
{ {
Oid relid = ((Form_pg_attribute) GETSTRUCT(atttup))->attrelid; Oid relid = ((Form_pg_attribute) GETSTRUCT(atttup))->attrelid;
heap_endscan(pg_type_scan);
heap_close(pg_type_desc);
heap_endscan(pg_attribute_scan); 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", elog(ERROR, "DeleteTypeTuple: att of type %s exists in relation %u",
&rel->rd_rel->relname, relid); &rel->rd_rel->relname, relid);
} }
heap_endscan(pg_attribute_scan); 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 * 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_delete(pg_type_desc, &tup->t_self, NULL);
heap_endscan(pg_type_scan); 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); bool istemp = (get_temp_rel_by_name(relname) != NULL);
/* ---------------- /* ----------------
* first open the relation. if the relation doesn't exist, * Open and lock the relation.
* heap_openr() returns NULL.
* ---------------- * ----------------
*/ */
rel = heap_openr(relname); rel = heap_openr(relname, AccessExclusiveLock);
if (rel == NULL)
elog(ERROR, "Relation '%s' does not exist", relname);
LockRelation(rel, AccessExclusiveLock);
rid = rel->rd_id; rid = rel->rd_id;
/* ---------------- /* ----------------
@ -1249,8 +1232,8 @@ heap_destroy_with_catalog(char *relname)
* ---------------- * ----------------
*/ */
/* allow temp of pg_class? Guess so. */ /* allow temp of pg_class? Guess so. */
if (!istemp && if (!istemp && !allowSystemTableMods &&
!allowSystemTableMods && IsSystemRelationName(RelationGetRelationName(rel)->data)) IsSystemRelationName(RelationGetRelationName(rel)->data))
elog(ERROR, "System relation '%s' cannot be destroyed", elog(ERROR, "System relation '%s' cannot be destroyed",
&rel->rd_rel->relname); &rel->rd_rel->relname);
@ -1330,9 +1313,12 @@ heap_destroy_with_catalog(char *relname)
rel->rd_nonameunlinked = TRUE; rel->rd_nonameunlinked = TRUE;
UnlockRelation(rel, AccessExclusiveLock); /*
* Close relcache entry, but *keep* AccessExclusiveLock on the
heap_close(rel); * 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 * flush the relation from the relcache
@ -1354,7 +1340,7 @@ heap_destroy(Relation rel)
if (!(rel->rd_isnoname) || !(rel->rd_nonameunlinked)) if (!(rel->rd_isnoname) || !(rel->rd_nonameunlinked))
smgrunlink(DEFAULT_SMGR, rel); smgrunlink(DEFAULT_SMGR, rel);
rel->rd_nonameunlinked = TRUE; rel->rd_nonameunlinked = TRUE;
heap_close(rel); heap_close(rel, NoLock);
RemoveFromNoNameRelList(rel); RemoveFromNoNameRelList(rel);
} }
@ -1542,13 +1528,13 @@ start:
values[Anum_pg_attrdef_adnum - 1] = attrdef->adnum; values[Anum_pg_attrdef_adnum - 1] = attrdef->adnum;
values[Anum_pg_attrdef_adbin - 1] = PointerGetDatum(textin(attrdef->adbin)); values[Anum_pg_attrdef_adbin - 1] = PointerGetDatum(textin(attrdef->adbin));
values[Anum_pg_attrdef_adsrc - 1] = PointerGetDatum(textin(attrdef->adsrc)); 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); tuple = heap_formtuple(adrel->rd_att, values, nulls);
CatalogOpenIndices(Num_pg_attrdef_indices, Name_pg_attrdef_indices, idescs); CatalogOpenIndices(Num_pg_attrdef_indices, Name_pg_attrdef_indices, idescs);
heap_insert(adrel, tuple); heap_insert(adrel, tuple);
CatalogIndexInsert(idescs, Num_pg_attrdef_indices, adrel, tuple); CatalogIndexInsert(idescs, Num_pg_attrdef_indices, adrel, tuple);
CatalogCloseIndices(Num_pg_attrdef_indices, idescs); 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_adbin - 1]));
pfree(DatumGetPointer(values[Anum_pg_attrdef_adsrc - 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_rcname - 1] = PointerGetDatum(namein(check->ccname));
values[Anum_pg_relcheck_rcbin - 1] = PointerGetDatum(textin(check->ccbin)); values[Anum_pg_relcheck_rcbin - 1] = PointerGetDatum(textin(check->ccbin));
values[Anum_pg_relcheck_rcsrc - 1] = PointerGetDatum(textin(check->ccsrc)); 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); tuple = heap_formtuple(rcrel->rd_att, values, nulls);
CatalogOpenIndices(Num_pg_relcheck_indices, Name_pg_relcheck_indices, idescs); CatalogOpenIndices(Num_pg_relcheck_indices, Name_pg_relcheck_indices, idescs);
heap_insert(rcrel, tuple); heap_insert(rcrel, tuple);
CatalogIndexInsert(idescs, Num_pg_relcheck_indices, rcrel, tuple); CatalogIndexInsert(idescs, Num_pg_relcheck_indices, rcrel, tuple);
CatalogCloseIndices(Num_pg_relcheck_indices, idescs); 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_rcname - 1]));
pfree(DatumGetPointer(values[Anum_pg_relcheck_rcbin - 1])); pfree(DatumGetPointer(values[Anum_pg_relcheck_rcbin - 1]));
pfree(DatumGetPointer(values[Anum_pg_relcheck_rcsrc - 1])); pfree(DatumGetPointer(values[Anum_pg_relcheck_rcsrc - 1]));
pfree(tuple); pfree(tuple);
return;
} }
static void static void
@ -1653,23 +1637,18 @@ RemoveAttrDefault(Relation rel)
ScanKeyData key; ScanKeyData key;
HeapTuple tup; HeapTuple tup;
adrel = heap_openr(AttrDefaultRelationName); adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&key, 0, Anum_pg_attrdef_adrelid, ScanKeyEntryInitialize(&key, 0, Anum_pg_attrdef_adrelid,
F_OIDEQ, rel->rd_id); F_OIDEQ, rel->rd_id);
LockRelation(adrel, AccessExclusiveLock);
adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key); adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key);
while (HeapTupleIsValid(tup = heap_getnext(adscan, 0))) while (HeapTupleIsValid(tup = heap_getnext(adscan, 0)))
heap_delete(adrel, &tup->t_self, NULL); heap_delete(adrel, &tup->t_self, NULL);
heap_endscan(adscan); heap_endscan(adscan);
heap_close(adrel, RowExclusiveLock);
UnlockRelation(adrel, AccessExclusiveLock);
heap_close(adrel);
} }
static void static void
@ -1680,23 +1659,18 @@ RemoveRelCheck(Relation rel)
ScanKeyData key; ScanKeyData key;
HeapTuple tup; HeapTuple tup;
rcrel = heap_openr(RelCheckRelationName); rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&key, 0, Anum_pg_relcheck_rcrelid, ScanKeyEntryInitialize(&key, 0, Anum_pg_relcheck_rcrelid,
F_OIDEQ, rel->rd_id); F_OIDEQ, rel->rd_id);
LockRelation(rcrel, AccessExclusiveLock);
rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key); rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key);
while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0))) while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0)))
heap_delete(rcrel, &tup->t_self, NULL); heap_delete(rcrel, &tup->t_self, NULL);
heap_endscan(rcscan); heap_endscan(rcscan);
heap_close(rcrel, RowExclusiveLock);
UnlockRelation(rcrel, AccessExclusiveLock);
heap_close(rcrel);
} }
static void static void
@ -1712,6 +1686,4 @@ RemoveConstraints(Relation rel)
if (constr->num_check > 0) if (constr->num_check > 0)
RemoveRelCheck(rel); RemoveRelCheck(rel);
return;
} }

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 * INTERFACE ROUTINES
@ -378,7 +378,7 @@ AccessMethodObjectIdGetForm(Oid accessMethodObjectId)
* fetch the desired access method tuple * 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_scan = heap_beginscan(pg_am_desc, 0, SnapshotNow, 1, &key);
pg_am_tuple = heap_getnext(pg_am_scan, 0); pg_am_tuple = heap_getnext(pg_am_scan, 0);
@ -390,7 +390,7 @@ AccessMethodObjectIdGetForm(Oid accessMethodObjectId)
if (!HeapTupleIsValid(pg_am_tuple)) if (!HeapTupleIsValid(pg_am_tuple))
{ {
heap_endscan(pg_am_scan); heap_endscan(pg_am_scan);
heap_close(pg_am_desc); heap_close(pg_am_desc, AccessShareLock);
return NULL; return NULL;
} }
@ -402,7 +402,7 @@ AccessMethodObjectIdGetForm(Oid accessMethodObjectId)
memcpy(aform, GETSTRUCT(pg_am_tuple), sizeof *aform); memcpy(aform, GETSTRUCT(pg_am_tuple), sizeof *aform);
heap_endscan(pg_am_scan); heap_endscan(pg_am_scan);
heap_close(pg_am_desc); heap_close(pg_am_desc, AccessShareLock);
return aform; return aform;
} }
@ -456,7 +456,7 @@ UpdateRelationRelation(Relation indexRelation, char *temp_relname)
Oid tupleOid; Oid tupleOid;
Relation idescs[Num_pg_class_indices]; 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 */ /* XXX Natts_pg_class_fixed is a hack - see pg_class.h */
tuple = heap_addheader(Natts_pg_class_fixed, tuple = heap_addheader(Natts_pg_class_fixed,
@ -491,7 +491,7 @@ UpdateRelationRelation(Relation indexRelation, char *temp_relname)
tupleOid = tuple->t_data->t_oid; tupleOid = tuple->t_data->t_oid;
pfree(tuple); pfree(tuple);
heap_close(pg_class); heap_close(pg_class, RowExclusiveLock);
return tupleOid; return tupleOid;
} }
@ -542,7 +542,7 @@ AppendAttributeTuples(Relation indexRelation, int numatts)
* XXX ADD INDEXING * XXX ADD INDEXING
* ---------------- * ----------------
*/ */
pg_attribute = heap_openr(AttributeRelationName); pg_attribute = heap_openr(AttributeRelationName, RowExclusiveLock);
/* ---------------- /* ----------------
* initialize *null, *replace and *value * initialize *null, *replace and *value
@ -628,7 +628,7 @@ AppendAttributeTuples(Relation indexRelation, int numatts)
if (cur_tuple) if (cur_tuple)
pfree(cur_tuple); pfree(cur_tuple);
heap_close(pg_attribute); heap_close(pg_attribute, RowExclusiveLock);
if (hasind) if (hasind)
CatalogCloseIndices(Num_pg_attr_indices, idescs); CatalogCloseIndices(Num_pg_attr_indices, idescs);
@ -734,7 +734,7 @@ UpdateIndexRelation(Oid indexoid,
* open the system catalog index relation * 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 * form a tuple to insert into pg_index
@ -755,7 +755,7 @@ UpdateIndexRelation(Oid indexoid,
* close the relation and free the tuple * close the relation and free the tuple
* ---------------- * ----------------
*/ */
heap_close(pg_index); heap_close(pg_index, RowExclusiveLock);
pfree(predText); pfree(predText);
pfree(indexForm); pfree(indexForm);
pfree(tuple); pfree(tuple);
@ -810,7 +810,7 @@ UpdateIndexPredicate(Oid indexoid, Node *oldPred, Node *predicate)
predText = (text *) fmgr(F_TEXTIN, ""); predText = (text *) fmgr(F_TEXTIN, "");
/* open the index system catalog relation */ /* open the index system catalog relation */
pg_index = heap_openr(IndexRelationName); pg_index = heap_openr(IndexRelationName, RowExclusiveLock);
tuple = SearchSysCacheTuple(INDEXRELID, tuple = SearchSysCacheTuple(INDEXRELID,
ObjectIdGetDatum(indexoid), ObjectIdGetDatum(indexoid),
@ -832,7 +832,7 @@ UpdateIndexPredicate(Oid indexoid, Node *oldPred, Node *predicate)
heap_replace(pg_index, &newtup->t_self, newtup, NULL); heap_replace(pg_index, &newtup->t_self, newtup, NULL);
pfree(newtup); pfree(newtup);
heap_close(pg_index); heap_close(pg_index, RowExclusiveLock);
pfree(predText); pfree(predText);
} }
@ -956,12 +956,10 @@ index_create(char *heapRelationName,
*/ */
heapoid = GetHeapRelationOid(heapRelationName, indexRelationName, istemp); 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 * construct new tuple descriptor
@ -1070,16 +1068,20 @@ index_create(char *heapRelationName,
* the index yet. We'll be creating more indices and classes later, * 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 * so we delay filling them in until just before we're done with
* bootstrapping. Otherwise, we call the routine that constructs the * 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()) if (IsBootstrapProcessingMode())
{ {
index_register(heapRelationName, indexRelationName, numatts, attNums, index_register(heapRelationName, indexRelationName, numatts, attNums,
parameterCount, parameter, funcInfo, predInfo); parameterCount, parameter, funcInfo, predInfo);
/* XXX shouldn't we close the heap and index rels here? */
} }
else else
{ {
heapRelation = heap_openr(heapRelationName);
index_build(heapRelation, indexRelation, numatts, attNums, index_build(heapRelation, indexRelation, numatts, attNums,
parameterCount, parameter, funcInfo, predInfo); parameterCount, parameter, funcInfo, predInfo);
} }
@ -1103,9 +1105,13 @@ index_destroy(Oid indexId)
Assert(OidIsValid(indexId)); Assert(OidIsValid(indexId));
/* Open now to obtain lock by referencing table? bjm */
userindexRelation = index_open(indexId); 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 * We do not allow DROP INDEX within a transaction block, because
* if the transaction is later rolled back there would be no way to * if the transaction is later rolled back there would be no way to
@ -1121,7 +1127,7 @@ index_destroy(Oid indexId)
* fix RELATION relation * fix RELATION relation
* ---------------- * ----------------
*/ */
relationRelation = heap_openr(RelationRelationName); relationRelation = heap_openr(RelationRelationName, RowExclusiveLock);
tuple = SearchSysCacheTupleCopy(RELOID, tuple = SearchSysCacheTupleCopy(RELOID,
ObjectIdGetDatum(indexId), ObjectIdGetDatum(indexId),
@ -1131,13 +1137,13 @@ index_destroy(Oid indexId)
heap_delete(relationRelation, &tuple->t_self, NULL); heap_delete(relationRelation, &tuple->t_self, NULL);
pfree(tuple); pfree(tuple);
heap_close(relationRelation); heap_close(relationRelation, RowExclusiveLock);
/* ---------------- /* ----------------
* fix ATTRIBUTE relation * fix ATTRIBUTE relation
* ---------------- * ----------------
*/ */
attributeRelation = heap_openr(AttributeRelationName); attributeRelation = heap_openr(AttributeRelationName, RowExclusiveLock);
attnum = 1; /* indexes start at 1 */ attnum = 1; /* indexes start at 1 */
@ -1150,7 +1156,7 @@ index_destroy(Oid indexId)
pfree(tuple); pfree(tuple);
attnum++; attnum++;
} }
heap_close(attributeRelation); heap_close(attributeRelation, RowExclusiveLock);
/* does something only if it is a temp index */ /* does something only if it is a temp index */
remove_temp_relation(indexId); remove_temp_relation(indexId);
@ -1159,16 +1165,16 @@ index_destroy(Oid indexId)
* fix INDEX relation * fix INDEX relation
* ---------------- * ----------------
*/ */
indexRelation = heap_openr(IndexRelationName, RowExclusiveLock);
tuple = SearchSysCacheTupleCopy(INDEXRELID, tuple = SearchSysCacheTupleCopy(INDEXRELID,
ObjectIdGetDatum(indexId), ObjectIdGetDatum(indexId),
0, 0, 0); 0, 0, 0);
Assert(HeapTupleIsValid(tuple)); Assert(HeapTupleIsValid(tuple));
indexRelation = heap_openr(IndexRelationName);
heap_delete(indexRelation, &tuple->t_self, NULL); heap_delete(indexRelation, &tuple->t_self, NULL);
pfree(tuple); pfree(tuple);
heap_close(indexRelation); heap_close(indexRelation, RowExclusiveLock);
/* /*
* flush cache and physically remove the file * flush cache and physically remove the file
@ -1179,7 +1185,8 @@ index_destroy(Oid indexId)
elog(ERROR, "index_destroy: unlink: %m"); elog(ERROR, "index_destroy: unlink: %m");
index_close(userindexRelation); 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); whichRel = RelationIdGetRelation(relid);
if (!RelationIsValid(whichRel)) if (!RelationIsValid(whichRel))
elog(ERROR, "UpdateStats: cannot open relation id %u", relid); elog(ERROR, "UpdateStats: cannot open relation id %u", relid);
LockRelation(whichRel, ShareLock);
/* ---------------- /* ----------------
* Find the RELATION relation tuple for the given relation. * Find the RELATION relation tuple for the given relation.
* ---------------- * ----------------
*/ */
pg_class = heap_openr(RelationRelationName); pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
if (!RelationIsValid(pg_class)) if (!RelationIsValid(pg_class))
elog(ERROR, "UpdateStats: could not open RELATION relation"); elog(ERROR, "UpdateStats: could not open RELATION relation");
@ -1300,7 +1312,7 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
{ {
if (IsBootstrapProcessingMode()) if (IsBootstrapProcessingMode())
heap_endscan(pg_class_scan); heap_endscan(pg_class_scan);
heap_close(pg_class); heap_close(pg_class, RowExclusiveLock);
elog(ERROR, "UpdateStats: cannot scan RELATION relation"); elog(ERROR, "UpdateStats: cannot scan RELATION relation");
} }
@ -1391,8 +1403,9 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
else else
heap_endscan(pg_class_scan); heap_endscan(pg_class_scan);
heap_close(pg_class); heap_close(pg_class, RowExclusiveLock);
heap_close(whichRel); /* 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); pfree(datum);
/* /*
* Okay, now update the reltuples and relpages statistics for both the * Since we just counted the tuples in the heap, we update its stats
* heap relation and the index. These statistics are used by the * in pg_class to guarantee that the planner takes advantage of the
* planner to choose a scan type. They are maintained generally by * index we just created. But, only update statistics during
* the vacuum daemon, but we update them here to make the index useful * normal index definitions, not for indices on system catalogs
* as soon as possible. * 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.
*/ */
UpdateStats(RelationGetRelid(heapRelation), reltuples, true); if (IsNormalProcessingMode())
UpdateStats(RelationGetRelid(indexRelation), indtuples, false);
if (oldPred != NULL)
{ {
if (indtuples == reltuples) Oid hrelid = RelationGetRelid(heapRelation);
predicate = NULL; Oid irelid = RelationGetRelid(indexRelation);
UpdateIndexPredicate(RelationGetRelid(indexRelation),
oldPred, predicate); 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; Form_pg_index index;
bool isunique; bool isunique;
pg_index = heap_openr(IndexRelationName); pg_index = heap_openr(IndexRelationName, AccessShareLock);
ScanKeyEntryInitialize(&skey[0], (bits16) 0x0, ScanKeyEntryInitialize(&skey[0], (bits16) 0x0,
Anum_pg_index_indexrelid, Anum_pg_index_indexrelid,
@ -1734,6 +1758,6 @@ IndexIsUniqueNoCache(Oid indexId)
isunique = index->indisunique; isunique = index->indisunique;
heap_endscan(scandesc); heap_endscan(scandesc);
heap_close(pg_index); heap_close(pg_index, AccessShareLock);
return isunique; return isunique;
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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; return false;
} }
pg_class = heap_openr(RelationRelationName); pg_class = heap_openr(RelationRelationName, AccessShareLock);
htup = ClassOidIndexScan(pg_class, catId); htup = ClassOidIndexScan(pg_class, catId);
heap_close(pg_class); heap_close(pg_class, AccessShareLock);
if (!HeapTupleIsValid(htup)) if (!HeapTupleIsValid(htup))
{ {

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 else
nulls[Anum_pg_aggregate_agginitval2 - 1] = 'n'; nulls[Anum_pg_aggregate_agginitval2 - 1] = 'n';
if (!RelationIsValid(aggdesc = heap_openr(AggregateRelationName))) aggdesc = heap_openr(AggregateRelationName, RowExclusiveLock);
elog(ERROR, "AggregateCreate: could not open '%s'",
AggregateRelationName);
tupDesc = aggdesc->rd_att; tupDesc = aggdesc->rd_att;
if (!HeapTupleIsValid(tup = heap_formtuple(tupDesc, if (!HeapTupleIsValid(tup = heap_formtuple(tupDesc,
values, values,
@ -245,8 +242,7 @@ AggregateCreate(char *aggName,
elog(ERROR, "AggregateCreate: heap_formtuple failed"); elog(ERROR, "AggregateCreate: heap_formtuple failed");
if (!OidIsValid(heap_insert(aggdesc, tup))) if (!OidIsValid(heap_insert(aggdesc, tup)))
elog(ERROR, "AggregateCreate: heap_insert failed"); elog(ERROR, "AggregateCreate: heap_insert failed");
heap_close(aggdesc); heap_close(aggdesc, RowExclusiveLock);
} }
char * char *
@ -264,6 +260,14 @@ AggNameGetInitVal(char *aggName, Oid basetype, int xfuncno, bool *isNull)
Assert(PointerIsValid(isNull)); Assert(PointerIsValid(isNull));
Assert(xfuncno == 1 || xfuncno == 2); 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, tup = SearchSysCacheTuple(AGGNAME,
PointerGetDatum(aggName), PointerGetDatum(aggName),
ObjectIdGetDatum(basetype), ObjectIdGetDatum(basetype),
@ -277,21 +281,12 @@ AggNameGetInitVal(char *aggName, Oid basetype, int xfuncno, bool *isNull)
initValAttno = Anum_pg_aggregate_agginitval1; initValAttno = Anum_pg_aggregate_agginitval1;
} }
else else
/* can only be 1 or 2 */
{ {
/* can only be 1 or 2 */
transtype = ((Form_pg_aggregate) GETSTRUCT(tup))->aggtranstype2; transtype = ((Form_pg_aggregate) GETSTRUCT(tup))->aggtranstype2;
initValAttno = Anum_pg_aggregate_agginitval2; 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, textInitVal = (text *) fastgetattr(tup, initValAttno,
RelationGetDescr(aggRel), RelationGetDescr(aggRel),
isNull); isNull);
@ -299,11 +294,12 @@ AggNameGetInitVal(char *aggName, Oid basetype, int xfuncno, bool *isNull)
*isNull = true; *isNull = true;
if (*isNull) if (*isNull)
{ {
heap_close(aggRel); heap_close(aggRel, AccessShareLock);
return (char *) NULL; return (char *) NULL;
} }
strInitVal = textout(textInitVal); strInitVal = textout(textInitVal);
heap_close(aggRel);
heap_close(aggRel, AccessShareLock);
tup = SearchSysCacheTuple(TYPOID, tup = SearchSysCacheTuple(TYPOID,
ObjectIdGetDatum(transtype), ObjectIdGetDatum(transtype),

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* these routines moved here from commands/define.c and somewhat cleaned up. * these routines moved here from commands/define.c and somewhat cleaned up.
@ -199,7 +199,7 @@ OperatorGet(char *operatorName,
* open the pg_operator relation * 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 * 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. * close the relation and return the operator oid.
* ---------------- * ----------------
*/ */
heap_close(pg_operator_desc); heap_close(pg_operator_desc, AccessShareLock);
return operatorObjectId; return operatorObjectId;
} }
@ -341,7 +341,7 @@ OperatorShellMake(char *operatorName,
* open pg_operator * 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 * add a "shell" operator tuple to the operator relation
@ -356,7 +356,7 @@ OperatorShellMake(char *operatorName,
* close the operator relation and return the oid. * close the operator relation and return the oid.
* ---------------- * ----------------
*/ */
heap_close(pg_operator_desc); heap_close(pg_operator_desc, RowExclusiveLock);
return operatorObjectId; return operatorObjectId;
} }
@ -754,10 +754,11 @@ OperatorDef(char *operatorName,
/* last three fields were filled in above */ /* 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 * If we are adding to an operator shell, get its t_self
*/ */
pg_operator_desc = heap_openr(OperatorRelationName);
if (operatorObjectId) if (operatorObjectId)
{ {
@ -798,7 +799,7 @@ OperatorDef(char *operatorName,
operatorObjectId = tup->t_data->t_oid; 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 * 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] = ' '; nulls[i] = ' ';
} }
pg_operator_desc = heap_openr(OperatorRelationName); pg_operator_desc = heap_openr(OperatorRelationName, RowExclusiveLock);
/* check and update the commutator, if necessary */ /* check and update the commutator, if necessary */
opKey[0].sk_argument = ObjectIdGetDatum(commId); opKey[0].sk_argument = ObjectIdGetDatum(commId);
@ -908,7 +909,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
} }
heap_endscan(pg_operator_scan); heap_endscan(pg_operator_scan);
heap_close(pg_operator_desc); heap_close(pg_operator_desc, RowExclusiveLock);
return; return;
} }
@ -964,7 +965,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
heap_endscan(pg_operator_scan); heap_endscan(pg_operator_scan);
heap_close(pg_operator_desc); heap_close(pg_operator_desc, RowExclusiveLock);
} }

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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, prosrc); /* prosrc */
values[i++] = (Datum) fmgr(F_TEXTIN, probin); /* probin */ values[i++] = (Datum) fmgr(F_TEXTIN, probin); /* probin */
rel = heap_openr(ProcedureRelationName); rel = heap_openr(ProcedureRelationName, RowExclusiveLock);
tupDesc = rel->rd_att; tupDesc = rel->rd_att;
tup = heap_formtuple(tupDesc, tup = heap_formtuple(tupDesc,
@ -294,6 +294,6 @@ ProcedureCreate(char *procedureName,
CatalogIndexInsert(idescs, Num_pg_proc_indices, rel, tup); CatalogIndexInsert(idescs, Num_pg_proc_indices, rel, tup);
CatalogCloseIndices(Num_pg_proc_indices, idescs); CatalogCloseIndices(Num_pg_proc_indices, idescs);
} }
heap_close(rel); heap_close(rel, RowExclusiveLock);
return tup->t_data->t_oid; return tup->t_data->t_oid;
} }

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 * 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 * 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. * close the type relation and return the type oid.
* ---------------- * ----------------
*/ */
heap_close(pg_type_desc); heap_close(pg_type_desc, AccessShareLock);
return typeoid; return typeoid;
} }
@ -248,7 +248,7 @@ TypeShellMake(char *typeName)
* open pg_type * open pg_type
* ---------------- * ----------------
*/ */
pg_type_desc = heap_openr(TypeRelationName); pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
/* ---------------- /* ----------------
* insert the shell tuple * insert the shell tuple
@ -260,7 +260,7 @@ TypeShellMake(char *typeName)
* close pg_type and return the tuple's oid. * close pg_type and return the tuple's oid.
* ---------------- * ----------------
*/ */
heap_close(pg_type_desc); heap_close(pg_type_desc, RowExclusiveLock);
return typoid; return typoid;
} }
@ -457,14 +457,7 @@ TypeCreate(char *typeName,
* open pg_type and begin a scan for the type name. * open pg_type and begin a scan for the type name.
* ---------------- * ----------------
*/ */
pg_type_desc = heap_openr(TypeRelationName); pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
/* -----------------
* 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);
typeKey[0].sk_argument = PointerGetDatum(typeName); typeKey[0].sk_argument = PointerGetDatum(typeName);
pg_type_scan = heap_beginscan(pg_type_desc, 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); CatalogIndexInsert(idescs, Num_pg_type_indices, pg_type_desc, tup);
CatalogCloseIndices(Num_pg_type_indices, idescs); CatalogCloseIndices(Num_pg_type_indices, idescs);
} }
UnlockRelation(pg_type_desc, AccessExclusiveLock);
heap_close(pg_type_desc); heap_close(pg_type_desc, RowExclusiveLock);
return typeObjectId; return typeObjectId;
} }
@ -541,7 +534,7 @@ TypeRename(char *oldTypeName, char *newTypeName)
HeapTuple oldtup, HeapTuple oldtup,
newtup; newtup;
pg_type_desc = heap_openr(TypeRelationName); pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
oldtup = SearchSysCacheTupleCopy(TYPNAME, oldtup = SearchSysCacheTupleCopy(TYPNAME,
PointerGetDatum(oldTypeName), PointerGetDatum(oldTypeName),
@ -549,7 +542,7 @@ TypeRename(char *oldTypeName, char *newTypeName)
if (!HeapTupleIsValid(oldtup)) if (!HeapTupleIsValid(oldtup))
{ {
heap_close(pg_type_desc); heap_close(pg_type_desc, RowExclusiveLock);
elog(ERROR, "TypeRename: type %s not defined", oldTypeName); elog(ERROR, "TypeRename: type %s not defined", oldTypeName);
} }
@ -559,7 +552,7 @@ TypeRename(char *oldTypeName, char *newTypeName)
if (HeapTupleIsValid(newtup)) if (HeapTupleIsValid(newtup))
{ {
pfree(oldtup); pfree(oldtup);
heap_close(pg_type_desc); heap_close(pg_type_desc, RowExclusiveLock);
elog(ERROR, "TypeRename: type %s already defined", newTypeName); elog(ERROR, "TypeRename: type %s already defined", newTypeName);
} }
@ -575,7 +568,7 @@ TypeRename(char *oldTypeName, char *newTypeName)
CatalogCloseIndices(Num_pg_type_indices, idescs); CatalogCloseIndices(Num_pg_type_indices, idescs);
pfree(oldtup); pfree(oldtup);
heap_close(pg_type_desc); heap_close(pg_type_desc, RowExclusiveLock);
} }
/* /*

View File

@ -6,7 +6,7 @@
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/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, since by assumption it is only called from outside any
* transaction. * transaction.
* *
* Note that the system's use of pg_listener is confined to very short * Although we grab AccessExclusiveLock on pg_listener for any operation,
* intervals at the end of a transaction that contains NOTIFY statements, * the lock is never held very long, so it shouldn't cause too much of
* or during the transaction caused by an inbound SIGUSR2. So the fact that * a performance problem.
* 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.
* *
* An application that listens on the same relname it notifies will get * 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, * 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); 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) if (!pendingNotifies)
pendingNotifies = DLNewList(); pendingNotifies = DLNewList();
notifyName = strdup(relname); /* no point in making duplicate entries in the list ... */
DLAddHead(pendingNotifies, DLNewElem(notifyName)); if (!AsyncExistsPendingNotify(relname))
{
/* /*
* NOTE: we could check to see if pendingNotifies already has an entry * We allocate list memory from the global malloc pool to ensure
* for relname, and thus avoid making duplicate entries. However, * that it will live until we want to use it. This is probably not
* most apps probably don't notify the same name multiple times per * necessary any longer, since we will use it before the end of the
* transaction, so we'd likely just be wasting cycles to make such a * transaction. DLList only knows how to use malloc() anyway, but we
* check. AsyncExistsPendingNotify() doesn't really care whether the * could probably palloc() the strings...
* list contains duplicates... */
*/ notifyName = strdup(relname);
DLAddHead(pendingNotifies, DLNewElem(notifyName));
}
} }
/* /*
@ -212,8 +200,7 @@ Async_Listen(char *relname, int pid)
TPRINTF(TRACE_NOTIFY, "Async_Listen: %s", relname); TPRINTF(TRACE_NOTIFY, "Async_Listen: %s", relname);
lRel = heap_openr(ListenerRelationName); lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
LockRelation(lRel, AccessExclusiveLock);
tdesc = RelationGetDescr(lRel); tdesc = RelationGetDescr(lRel);
/* Detect whether we are already listening on this relname */ /* Detect whether we are already listening on this relname */
@ -236,9 +223,8 @@ Async_Listen(char *relname, int pid)
if (alreadyListener) if (alreadyListener)
{ {
heap_close(lRel, AccessExclusiveLock);
elog(NOTICE, "Async_Listen: We are already listening on %s", relname); elog(NOTICE, "Async_Listen: We are already listening on %s", relname);
UnlockRelation(lRel, AccessExclusiveLock);
heap_close(lRel);
return; return;
} }
@ -262,8 +248,7 @@ Async_Listen(char *relname, int pid)
heap_insert(lRel, newtup); heap_insert(lRel, newtup);
pfree(newtup); pfree(newtup);
UnlockRelation(lRel, AccessExclusiveLock); heap_close(lRel, AccessExclusiveLock);
heap_close(lRel);
/* /*
* now that we are listening, make sure we will unlisten before dying. * 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); TPRINTF(TRACE_NOTIFY, "Async_Unlisten %s", relname);
lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
/* Note we assume there can be only one matching tuple. */ /* Note we assume there can be only one matching tuple. */
lTuple = SearchSysCacheTuple(LISTENREL, PointerGetDatum(relname), lTuple = SearchSysCacheTuple(LISTENREL, PointerGetDatum(relname),
Int32GetDatum(pid), Int32GetDatum(pid),
0, 0); 0, 0);
if (lTuple != NULL) if (lTuple != NULL)
{
lRel = heap_openr(ListenerRelationName);
LockRelation(lRel, AccessExclusiveLock);
heap_delete(lRel, &lTuple->t_self, NULL); heap_delete(lRel, &lTuple->t_self, NULL);
UnlockRelation(lRel, AccessExclusiveLock); heap_close(lRel, AccessExclusiveLock);
heap_close(lRel);
}
/* /*
* We do not complain about unlistening something not being listened; * We do not complain about unlistening something not being listened;
@ -354,8 +335,7 @@ Async_UnlistenAll()
TPRINTF(TRACE_NOTIFY, "Async_UnlistenAll"); TPRINTF(TRACE_NOTIFY, "Async_UnlistenAll");
lRel = heap_openr(ListenerRelationName); lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
LockRelation(lRel, AccessExclusiveLock);
tdesc = RelationGetDescr(lRel); tdesc = RelationGetDescr(lRel);
/* Find and delete all entries with my listenerPID */ /* Find and delete all entries with my listenerPID */
@ -369,8 +349,7 @@ Async_UnlistenAll()
heap_delete(lRel, &lTuple->t_self, NULL); heap_delete(lRel, &lTuple->t_self, NULL);
heap_endscan(sRel); heap_endscan(sRel);
UnlockRelation(lRel, AccessExclusiveLock); heap_close(lRel, AccessExclusiveLock);
heap_close(lRel);
} }
/* /*
@ -462,8 +441,7 @@ AtCommit_Notify()
TPRINTF(TRACE_NOTIFY, "AtCommit_Notify"); TPRINTF(TRACE_NOTIFY, "AtCommit_Notify");
lRel = heap_openr(ListenerRelationName); lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
LockRelation(lRel, AccessExclusiveLock);
tdesc = RelationGetDescr(lRel); tdesc = RelationGetDescr(lRel);
sRel = heap_beginscan(lRel, 0, SnapshotNow, 0, (ScanKey) NULL); sRel = heap_beginscan(lRel, 0, SnapshotNow, 0, (ScanKey) NULL);
@ -542,10 +520,13 @@ AtCommit_Notify()
heap_endscan(sRel); heap_endscan(sRel);
/* /*
* We do not do RelationUnsetLockForWrite(lRel) here, because the * We do NOT release the lock on pg_listener here; we need to hold it
* transaction is about to be committed anyway. * 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(); ClearPendingNotifies();
@ -756,8 +737,7 @@ ProcessIncomingNotify(void)
StartTransactionCommand(); StartTransactionCommand();
lRel = heap_openr(ListenerRelationName); lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
LockRelation(lRel, AccessExclusiveLock);
tdesc = RelationGetDescr(lRel); tdesc = RelationGetDescr(lRel);
/* Scan only entries with my listenerPID */ /* Scan only entries with my listenerPID */
@ -794,10 +774,13 @@ ProcessIncomingNotify(void)
heap_endscan(sRel); heap_endscan(sRel);
/* /*
* We do not do RelationUnsetLockForWrite(lRel) here, because the * We do NOT release the lock on pg_listener here; we need to hold it
* transaction is about to be committed anyway. * 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(); CommitTransactionCommand();

View File

@ -14,7 +14,7 @@
* *
* *
* IDENTIFICATION * 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 * 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, AccessExclusiveLock);
OIDOldHeap = RelationGetRelid(OldHeap);
OldHeap = heap_openr(oldrelname);
if (!RelationIsValid(OldHeap))
{
elog(ERROR, "cluster: unknown relation: \"%s\"",
oldrelname);
}
OIDOldHeap = RelationGetRelid(OldHeap); /* Get OID for the index
* scan */
OldIndex = index_openr(oldindexname); /* Open old index relation */ OldIndex = index_openr(oldindexname); /* Open old index relation */
if (!RelationIsValid(OldIndex)) LockRelation(OldIndex, AccessExclusiveLock);
{ OIDOldIndex = RelationGetRelid(OldIndex);
elog(ERROR, "cluster: unknown index: \"%s\"",
oldindexname);
}
OIDOldIndex = RelationGetRelid(OldIndex); /* OID for the index scan */
heap_close(OldHeap); heap_close(OldHeap, NoLock); /* do NOT give up the locks */
index_close(OldIndex); 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 * 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 * 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 * 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); NewHeap = copy_heap(OIDOldHeap);
OIDNewHeap = RelationGetRelid(NewHeap); OIDNewHeap = RelationGetRelid(NewHeap);
@ -171,7 +162,7 @@ cluster(char *oldrelname, char *oldindexname)
renamerel(NewIndexName, saveoldindexname); renamerel(NewIndexName, saveoldindexname);
/* /*
* Again flush all the buffers. * Again flush all the buffers. XXX perhaps not needed?
*/ */
CommitTransactionCommand(); CommitTransactionCommand();
StartTransactionCommand(); StartTransactionCommand();
@ -193,7 +184,7 @@ copy_heap(Oid OIDOldHeap)
*/ */
snprintf(NewName, NAMEDATALEN, "temp_%x", OIDOldHeap); snprintf(NewName, NAMEDATALEN, "temp_%x", OIDOldHeap);
OldHeap = heap_open(OIDOldHeap); OldHeap = heap_open(OIDOldHeap, AccessExclusiveLock);
OldHeapDesc = RelationGetDescr(OldHeap); OldHeapDesc = RelationGetDescr(OldHeap);
/* /*
@ -209,10 +200,11 @@ copy_heap(Oid OIDOldHeap)
if (!OidIsValid(OIDNewHeap)) if (!OidIsValid(OIDNewHeap))
elog(ERROR, "clusterheap: cannot create temporary heap relation\n"); 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(NewHeap, AccessExclusiveLock);
heap_close(OldHeap); heap_close(OldHeap, AccessExclusiveLock);
return NewHeap; return NewHeap;
} }
@ -233,7 +225,7 @@ copy_index(Oid OIDOldIndex, Oid OIDNewHeap)
int natts; int natts;
FuncIndexInfo *finfo; FuncIndexInfo *finfo;
NewHeap = heap_open(OIDNewHeap); NewHeap = heap_open(OIDNewHeap, AccessExclusiveLock);
OldIndex = index_open(OIDOldIndex); OldIndex = index_open(OIDOldIndex);
/* /*
@ -305,8 +297,8 @@ copy_index(Oid OIDOldIndex, Oid OIDNewHeap)
Old_pg_index_Form->indisunique, Old_pg_index_Form->indisunique,
Old_pg_index_Form->indisprimary); Old_pg_index_Form->indisprimary);
heap_close(OldIndex); index_close(OldIndex);
heap_close(NewHeap); 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 * Open the relations I need. Scan through the OldHeap on the OldIndex
* and insert each tuple into the NewHeap. * and insert each tuple into the NewHeap.
*/ */
LocalNewHeap = (Relation) heap_open(OIDNewHeap); LocalNewHeap = heap_open(OIDNewHeap, AccessExclusiveLock);
LocalOldHeap = (Relation) heap_open(OIDOldHeap); LocalOldHeap = heap_open(OIDOldHeap, AccessExclusiveLock);
LocalOldIndex = (Relation) index_open(OIDOldIndex); LocalOldIndex = (Relation) index_open(OIDOldIndex);
ScanDesc = index_beginscan(LocalOldIndex, false, 0, (ScanKey) NULL); ScanDesc = index_beginscan(LocalOldIndex, false, 0, (ScanKey) NULL);
@ -344,6 +336,6 @@ rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
index_endscan(ScanDesc); index_endscan(ScanDesc);
index_close(LocalOldIndex); index_close(LocalOldIndex);
heap_close(LocalOldHeap); heap_close(LocalOldHeap, AccessExclusiveLock);
heap_close(LocalNewHeap); heap_close(LocalNewHeap, AccessExclusiveLock);
} }

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* The PortalExecutorHeapMemory crap needs to be eliminated * The PortalExecutorHeapMemory crap needs to be eliminated
@ -283,6 +283,7 @@ PerformAddAttribute(char *relationName,
{ {
Relation rel, Relation rel,
attrdesc; attrdesc;
Oid myrelid;
HeapTuple reltup; HeapTuple reltup;
HeapTuple attributeTuple; HeapTuple attributeTuple;
Form_pg_attribute attribute; Form_pg_attribute attribute;
@ -310,6 +311,14 @@ PerformAddAttribute(char *relationName,
relationName); relationName);
#endif #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 * we can't add a not null attribute
*/ */
@ -331,20 +340,10 @@ PerformAddAttribute(char *relationName,
{ {
if (inherits) if (inherits)
{ {
Oid myrelid, Oid childrelid;
childrelid;
List *child, List *child,
*children; *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 */ /* this routine is actually in the planner */
children = find_all_inheritors(lconsi(myrelid, NIL), NIL); children = find_all_inheritors(lconsi(myrelid, NIL), NIL);
@ -358,31 +357,23 @@ PerformAddAttribute(char *relationName,
childrelid = lfirsti(child); childrelid = lfirsti(child);
if (childrelid == myrelid) if (childrelid == myrelid)
continue; continue;
rel = heap_open(childrelid); rel = heap_open(childrelid, AccessExclusiveLock);
if (!RelationIsValid(rel))
{
elog(ERROR, "PerformAddAttribute: can't find catalog entry for inheriting class with oid %u",
childrelid);
}
PerformAddAttribute((rel->rd_rel->relname).data, PerformAddAttribute((rel->rd_rel->relname).data,
userName, false, colDef); userName, false, colDef);
heap_close(rel); heap_close(rel, AccessExclusiveLock);
} }
} }
} }
rel = heap_openr(RelationRelationName); rel = heap_openr(RelationRelationName, RowExclusiveLock);
reltup = SearchSysCacheTupleCopy(RELNAME, reltup = SearchSysCacheTupleCopy(RELNAME,
PointerGetDatum(relationName), PointerGetDatum(relationName),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(reltup)) if (!HeapTupleIsValid(reltup))
{
heap_close(rel);
elog(ERROR, "PerformAddAttribute: relation \"%s\" not found", elog(ERROR, "PerformAddAttribute: relation \"%s\" not found",
relationName); relationName);
}
/* /*
* XXX is the following check sufficient? * XXX is the following check sufficient?
@ -391,23 +382,15 @@ PerformAddAttribute(char *relationName,
{ {
elog(ERROR, "PerformAddAttribute: index relation \"%s\" not changed", elog(ERROR, "PerformAddAttribute: index relation \"%s\" not changed",
relationName); relationName);
return;
} }
minattnum = ((Form_pg_class) GETSTRUCT(reltup))->relnatts; minattnum = ((Form_pg_class) GETSTRUCT(reltup))->relnatts;
maxatts = minattnum + 1; maxatts = minattnum + 1;
if (maxatts > MaxHeapAttributeNumber) if (maxatts > MaxHeapAttributeNumber)
{
pfree(reltup);
heap_close(rel);
elog(ERROR, "PerformAddAttribute: relations limited to %d attributes", elog(ERROR, "PerformAddAttribute: relations limited to %d attributes",
MaxHeapAttributeNumber); MaxHeapAttributeNumber);
}
attrdesc = heap_openr(AttributeRelationName); attrdesc = heap_openr(AttributeRelationName, RowExclusiveLock);
Assert(attrdesc);
Assert(RelationGetForm(attrdesc));
/* /*
* Open all (if any) pg_attribute indices * Open all (if any) pg_attribute indices
@ -438,12 +421,8 @@ PerformAddAttribute(char *relationName,
0, 0); 0, 0);
if (HeapTupleIsValid(tup)) if (HeapTupleIsValid(tup))
{
heap_close(attrdesc);
heap_close(rel);
elog(ERROR, "PerformAddAttribute: attribute \"%s\" already exists in class \"%s\"", elog(ERROR, "PerformAddAttribute: attribute \"%s\" already exists in class \"%s\"",
colDef->colname, relationName); colDef->colname, relationName);
}
/* /*
* check to see if it is an array attribute. * check to see if it is an array attribute.
@ -490,7 +469,8 @@ PerformAddAttribute(char *relationName,
if (hasindex) if (hasindex)
CatalogCloseIndices(Num_pg_attr_indices, idescs); CatalogCloseIndices(Num_pg_attr_indices, idescs);
heap_close(attrdesc);
heap_close(attrdesc, RowExclusiveLock);
((Form_pg_class) GETSTRUCT(reltup))->relnatts = maxatts; ((Form_pg_class) GETSTRUCT(reltup))->relnatts = maxatts;
heap_replace(rel, &reltup->t_self, reltup, NULL); heap_replace(rel, &reltup->t_self, reltup, NULL);
@ -501,7 +481,7 @@ PerformAddAttribute(char *relationName,
CatalogCloseIndices(Num_pg_class_indices, ridescs); CatalogCloseIndices(Num_pg_class_indices, ridescs);
pfree(reltup); pfree(reltup);
heap_close(rel); heap_close(rel, RowExclusiveLock);
} }
void void
@ -510,9 +490,9 @@ LockTableCommand(LockStmt *lockstmt)
Relation rel; Relation rel;
int aclresult; int aclresult;
rel = heap_openr(lockstmt->relname); rel = heap_openr(lockstmt->relname, NoLock);
if (rel == NULL) if (! RelationIsValid(rel))
elog(ERROR, "LOCK TABLE: relation %s can't be openned", lockstmt->relname); elog(ERROR, "Relation '%s' does not exist", lockstmt->relname);
if (lockstmt->mode == AccessShareLock) if (lockstmt->mode == AccessShareLock)
aclresult = pg_aclcheck(lockstmt->relname, GetPgUserName(), ACL_RD); aclresult = pg_aclcheck(lockstmt->relname, GetPgUserName(), ACL_RD);
@ -524,4 +504,5 @@ LockTableCommand(LockStmt *lockstmt)
LockRelation(rel, lockstmt->mode); LockRelation(rel, lockstmt->mode);
heap_close(rel, NoLock); /* close rel, keep lock */
} }

View File

@ -6,7 +6,7 @@
* *
* *
* IDENTIFICATION * 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; Relation rel;
extern char *UserName; /* defined in global.c */ extern char *UserName; /* defined in global.c */
const AclMode required_access = from ? ACL_WR : ACL_RD; 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; int result;
rel = heap_openr(relname); rel = heap_openr(relname, required_lock);
if (rel == NULL)
elog(ERROR, "COPY command failed. Class %s "
"does not exist.", relname);
result = pg_aclcheck(relname, UserName, required_access); result = pg_aclcheck(relname, UserName, required_access);
if (result != ACLCHECK_OK) if (result != ACLCHECK_OK)
elog(ERROR, "%s: %s", relname, aclcheck_error_strings[result]); elog(ERROR, "%s: %s", relname, aclcheck_error_strings[result]);
/* Above should not return */ else if (!pipe && !superuser())
else if (!superuser() && !pipe)
elog(ERROR, "You must have Postgres superuser privilege to do a COPY " elog(ERROR, "You must have Postgres superuser privilege to do a COPY "
"directly to or from a file. Anyone can COPY to stdout or " "directly to or from a file. Anyone can COPY to stdout or "
"from stdin. Psql's \\copy command also works for anyone."); "from stdin. Psql's \\copy command also works for anyone.");
/* Above should not return. */
else else
{ {
if (from) if (from)
@ -342,6 +342,8 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
pq_endcopyout(false); 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(elements);
pfree(typmod); pfree(typmod);
} }
heap_close(rel);
} }
static void static void
@ -905,20 +905,19 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
pfree(typmod); pfree(typmod);
} }
/* comments in execUtils.c */
if (has_index) if (has_index)
{ {
for (i = 0; i < n_indices; i++) for (i = 0; i < n_indices; i++)
{ {
if (index_rels[i] == NULL) if (index_rels[i] == NULL)
continue; continue;
/* see comments in ExecOpenIndices() in execUtils.c */
if ((index_rels[i])->rd_rel->relam != BTREE_AM_OID && if ((index_rels[i])->rd_rel->relam != BTREE_AM_OID &&
(index_rels[i])->rd_rel->relam != HASH_AM_OID) (index_rels[i])->rd_rel->relam != HASH_AM_OID)
UnlockRelation(index_rels[i], AccessExclusiveLock); UnlockRelation(index_rels[i], AccessExclusiveLock);
index_close(index_rels[i]); 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 * Given the OID of a relation, return an array of index relation descriptors
* and the number of index relations. These relation descriptors are open * 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. * Space for the array itself is palloc'ed.
*/ */
@ -1017,7 +1016,7 @@ GetIndexRelations(Oid main_relation_oid,
int i; int i;
bool isnull; 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); scandesc = heap_beginscan(pg_index_rel, 0, SnapshotNow, 0, NULL);
tupDesc = RelationGetDescr(pg_index_rel); tupDesc = RelationGetDescr(pg_index_rel);
@ -1044,7 +1043,7 @@ GetIndexRelations(Oid main_relation_oid,
} }
heap_endscan(scandesc); 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... */ /* We cannot trust to relhasindex of the main_relation now, so... */
if (*n_indices == 0) 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) for (i = 0, scan = head; i < *n_indices; i++, scan = scan->next)
{ {
(*index_rels)[i] = index_open(scan->index_rel_oid); (*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 && if ((*index_rels)[i] != NULL &&
((*index_rels)[i])->rd_rel->relam != BTREE_AM_OID && ((*index_rels)[i])->rd_rel->relam != BTREE_AM_OID &&
((*index_rels)[i])->rd_rel->relam != HASH_AM_OID) ((*index_rels)[i])->rd_rel->relam != HASH_AM_OID)

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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) foreach(entry, schema)
{ {
List *rest;
ColumnDef *coldef = lfirst(entry); ColumnDef *coldef = lfirst(entry);
List *rest;
foreach(rest, lnext(entry)) foreach(rest, lnext(entry))
{ {
/* /*
* check for duplicated relation names * check for duplicated names within the new relation
*/ */
ColumnDef *restdef = lfirst(rest); ColumnDef *restdef = lfirst(rest);
@ -246,17 +245,14 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
TupleDesc tupleDesc; TupleDesc tupleDesc;
TupleConstr *constr; TupleConstr *constr;
relation = heap_openr(name); relation = heap_openr(name, AccessShareLock);
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);
tupleDesc = RelationGetDescr(relation); tupleDesc = RelationGetDescr(relation);
constr = tupleDesc->constr; 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--) for (attrno = relation->rd_rel->relnatts - 1; attrno >= 0; attrno--)
{ {
Form_pg_attribute attribute = tupleDesc->attrs[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 * wants the inherited schema to appear in the order they are
@ -386,7 +384,7 @@ StoreCatalogInheritance(Oid relationId, List *supers)
* Catalog INHERITS information. * Catalog INHERITS information.
* ---------------- * ----------------
*/ */
relation = heap_openr(InheritsRelationName); relation = heap_openr(InheritsRelationName, RowExclusiveLock);
desc = RelationGetDescr(relation); desc = RelationGetDescr(relation);
seqNumber = 1; seqNumber = 1;
@ -422,7 +420,7 @@ StoreCatalogInheritance(Oid relationId, List *supers)
seqNumber += 1; seqNumber += 1;
} }
heap_close(relation); heap_close(relation, RowExclusiveLock);
/* ---------------- /* ----------------
* Catalog IPL information. * Catalog IPL information.
@ -510,7 +508,7 @@ again:
* 3. * 3.
* ---------------- * ----------------
*/ */
relation = heap_openr(InheritancePrecidenceListRelationName); relation = heap_openr(InheritancePrecidenceListRelationName, RowExclusiveLock);
desc = RelationGetDescr(relation); desc = RelationGetDescr(relation);
seqNumber = 1; seqNumber = 1;
@ -537,7 +535,7 @@ again:
seqNumber += 1; seqNumber += 1;
} }
heap_close(relation); heap_close(relation, RowExclusiveLock);
} }
/* /*

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 the vacuum daemon */
stop_vacuum(dbpath, dbname); stop_vacuum(dbpath, dbname);
/* XXX what about stopping backends connected to the target database? */
path = ExpandDatabasePath(dbpath); path = ExpandDatabasePath(dbpath);
if (path == NULL) if (path == NULL)
elog(ERROR, "Unable to locate path '%s'" elog(ERROR, "Unable to locate path '%s'"
@ -189,6 +191,7 @@ check_permissions(char *command,
utup = SearchSysCacheTuple(USENAME, utup = SearchSysCacheTuple(USENAME,
PointerGetDatum(userName), PointerGetDatum(userName),
0, 0, 0); 0, 0, 0);
Assert(utup);
*userIdP = ((Form_pg_shadow) GETSTRUCT(utup))->usesysid; *userIdP = ((Form_pg_shadow) GETSTRUCT(utup))->usesysid;
use_super = ((Form_pg_shadow) GETSTRUCT(utup))->usesuper; use_super = ((Form_pg_shadow) GETSTRUCT(utup))->usesuper;
use_createdb = ((Form_pg_shadow) GETSTRUCT(utup))->usecreatedb; 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 */ /* Check to make sure database is owned by this user */
/* /*
* need the reldesc to get the database owner out of dbtup and to set * Acquire exclusive lock on pg_database from the beginning, even though
* a write lock on it. * 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); dbrel = heap_openr(DatabaseRelationName, AccessExclusiveLock);
if (!RelationIsValid(dbrel))
elog(FATAL, "%s: cannot open relation \"%-.*s\"",
command, DatabaseRelationName);
/*
* 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); dbtup = get_pg_dbtup(command, dbname, dbrel);
dbfound = HeapTupleIsValid(dbtup); dbfound = HeapTupleIsValid(dbtup);
@ -248,7 +242,8 @@ check_permissions(char *command,
else else
*dbIdP = InvalidOid; *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. * Now be sure that the user is allowed to do this.

View File

@ -4,7 +4,7 @@
* *
* Copyright (c) 1994-5, Regents of the University of California * 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; i = 0;
foreach(l, ((IndexScan *) plan)->indxid) foreach(l, ((IndexScan *) plan)->indxid)
{ {
relation = RelationIdCacheGetRelation((int) lfirst(l)); relation = RelationIdGetRelation(lfirsti(l));
Assert(relation);
if (++i > 1) if (++i > 1)
appendStringInfo(str, ", "); appendStringInfo(str, ", ");
appendStringInfo(str, appendStringInfo(str,
stringStringInfo((RelationGetRelationName(relation))->data)); stringStringInfo((RelationGetRelationName(relation))->data));
/* drop relcache refcount from RelationIdGetRelation */
RelationDecrementReferenceCount(relation);
} }
case T_SeqScan: case T_SeqScan:
if (((Scan *) plan)->scanrelid > 0) if (((Scan *) plan)->scanrelid > 0)

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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); FIsetProcOid(funcInfo, tuple->t_data->t_oid);
} }
heapRelation = heap_open(relationId); heapRelation = heap_open(relationId, ShareLock);
indexRelation = index_open(indexId); indexRelation = index_open(indexId);
LockRelation(heapRelation, ShareLock);
InitIndexStrategy(numberOfAttributes, indexRelation, accessMethodId); InitIndexStrategy(numberOfAttributes, indexRelation, accessMethodId);
index_build(heapRelation, indexRelation, numberOfAttributes, index_build(heapRelation, indexRelation, numberOfAttributes,
attributeNumberA, 0, NULL, funcInfo, predInfo); attributeNumberA, 0, NULL, funcInfo, predInfo);
/* heap and index rels are closed as a side-effect of index_build */
} }

View File

@ -120,15 +120,14 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
values[i++] = ObjectIdGetDatum(procTup->t_data->t_oid); values[i++] = ObjectIdGetDatum(procTup->t_data->t_oid);
values[i++] = (Datum) fmgr(F_TEXTIN, stmt->plcompiler); values[i++] = (Datum) fmgr(F_TEXTIN, stmt->plcompiler);
rel = heap_openr(LanguageRelationName); rel = heap_openr(LanguageRelationName, RowExclusiveLock);
tupDesc = rel->rd_att; tupDesc = rel->rd_att;
tup = heap_formtuple(tupDesc, values, nulls); tup = heap_formtuple(tupDesc, values, nulls);
heap_insert(rel, tup); heap_insert(rel, tup);
heap_close(rel); heap_close(rel, RowExclusiveLock);
return;
} }
@ -160,6 +159,8 @@ DropProceduralLanguage(DropPLangStmt *stmt)
*/ */
case_translate_language_name(stmt->plname, languageName); case_translate_language_name(stmt->plname, languageName);
rel = heap_openr(LanguageRelationName, RowExclusiveLock);
langTup = SearchSysCacheTupleCopy(LANNAME, langTup = SearchSysCacheTupleCopy(LANNAME,
PointerGetDatum(languageName), PointerGetDatum(languageName),
0, 0, 0); 0, 0, 0);
@ -167,14 +168,11 @@ DropProceduralLanguage(DropPLangStmt *stmt)
elog(ERROR, "Language %s doesn't exist", languageName); elog(ERROR, "Language %s doesn't exist", languageName);
if (!((Form_pg_language) GETSTRUCT(langTup))->lanispl) if (!((Form_pg_language) GETSTRUCT(langTup))->lanispl)
{
elog(ERROR, "Language %s isn't a created procedural language", elog(ERROR, "Language %s isn't a created procedural language",
languageName); languageName);
}
rel = heap_openr(LanguageRelationName);
heap_delete(rel, &langTup->t_self, NULL); heap_delete(rel, &langTup->t_self, NULL);
pfree(langTup); pfree(langTup);
heap_close(rel); heap_close(rel, RowExclusiveLock);
} }

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 else
oprtype = 'r'; oprtype = 'r';
relation = heap_openr(OperatorRelationName, RowExclusiveLock);
tup = SearchSysCacheTupleCopy(OPRNAME, tup = SearchSysCacheTupleCopy(OPRNAME,
PointerGetDatum(operatorName), PointerGetDatum(operatorName),
ObjectIdGetDatum(typeId1), ObjectIdGetDatum(typeId1),
ObjectIdGetDatum(typeId2), ObjectIdGetDatum(typeId2),
CharGetDatum(oprtype)); CharGetDatum(oprtype));
relation = heap_openr(OperatorRelationName);
if (HeapTupleIsValid(tup)) if (HeapTupleIsValid(tup))
{ {
#ifndef NO_SECURITY #ifndef NO_SECURITY
@ -117,7 +118,7 @@ RemoveOperator(char *operatorName, /* operator name */
} }
} }
pfree(tup); pfree(tup);
heap_close(relation); heap_close(relation, RowExclusiveLock);
} }
#ifdef NOTYET #ifdef NOTYET
@ -141,7 +142,7 @@ SingleOpOperatorRemove(Oid typeOid)
ScanKeyEntryInitialize(&key[0], ScanKeyEntryInitialize(&key[0],
0, 0, F_OIDEQ, (Datum) typeOid); 0, 0, F_OIDEQ, (Datum) typeOid);
rel = heap_openr(OperatorRelationName); rel = heap_openr(OperatorRelationName, RowExclusiveLock);
for (i = 0; i < 3; ++i) for (i = 0; i < 3; ++i)
{ {
key[0].sk_attno = attnums[i]; key[0].sk_attno = attnums[i];
@ -150,7 +151,7 @@ SingleOpOperatorRemove(Oid typeOid)
heap_delete(rel, &tup->t_self, NULL); heap_delete(rel, &tup->t_self, NULL);
heap_endscan(scan); heap_endscan(scan);
} }
heap_close(rel); heap_close(rel, RowExclusiveLock);
} }
/* /*
@ -187,7 +188,7 @@ AttributeAndRelationRemove(Oid typeOid)
oidptr = (struct oidlist *) palloc(sizeof(*oidptr)); oidptr = (struct oidlist *) palloc(sizeof(*oidptr));
oidptr->next = NULL; oidptr->next = NULL;
optr = oidptr; optr = oidptr;
rel = heap_openr(AttributeRelationName); rel = heap_openr(AttributeRelationName, AccessShareLock);
scan = heap_beginscan(rel, 0, SnapshotNow, 1, key); scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
while (HeapTupleIsValid(tup = heap_getnext(scan, 0))) while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
{ {
@ -197,14 +198,15 @@ AttributeAndRelationRemove(Oid typeOid)
} }
optr->next = NULL; optr->next = NULL;
heap_endscan(scan); heap_endscan(scan);
heap_close(rel); heap_close(rel, AccessShareLock);
optr = oidptr;
ScanKeyEntryInitialize(&key[0], 0, ScanKeyEntryInitialize(&key[0], 0,
ObjectIdAttributeNumber, ObjectIdAttributeNumber,
F_OIDEQ, (Datum) 0); F_OIDEQ, (Datum) 0);
optr = oidptr; /* get RowExclusiveLock because heap_destroy will need it */
rel = heap_openr(RelationRelationName); rel = heap_openr(RelationRelationName, RowExclusiveLock);
while (PointerIsValid((char *) optr->next)) while (PointerIsValid((char *) optr->next))
{ {
key[0].sk_argument = (Datum) (optr++)->reloid; key[0].sk_argument = (Datum) (optr++)->reloid;
@ -217,9 +219,9 @@ AttributeAndRelationRemove(Oid typeOid)
name = (((Form_pg_class) GETSTRUCT(tup))->relname).data; name = (((Form_pg_class) GETSTRUCT(tup))->relname).data;
heap_destroy_with_catalog(name); heap_destroy_with_catalog(name);
} }
heap_endscan(scan);
} }
heap_endscan(scan); heap_close(rel, RowExclusiveLock);
heap_close(rel);
} }
#endif /* NOTYET */ #endif /* NOTYET */
@ -245,18 +247,17 @@ RemoveType(char *typeName) /* type name to be removed */
typeName); typeName);
#endif #endif
relation = heap_openr(TypeRelationName); relation = heap_openr(TypeRelationName, RowExclusiveLock);
tup = SearchSysCacheTuple(TYPNAME, tup = SearchSysCacheTuple(TYPNAME,
PointerGetDatum(typeName), PointerGetDatum(typeName),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
{ {
heap_close(relation); heap_close(relation, RowExclusiveLock);
elog(ERROR, "RemoveType: type '%s' does not exist", typeName); elog(ERROR, "RemoveType: type '%s' does not exist", typeName);
} }
relation = heap_openr(TypeRelationName);
typeOid = tup->t_data->t_oid; typeOid = tup->t_data->t_oid;
heap_delete(relation, &tup->t_self, NULL); heap_delete(relation, &tup->t_self, NULL);
@ -267,14 +268,13 @@ RemoveType(char *typeName) /* type name to be removed */
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
{ {
heap_close(relation); heap_close(relation, RowExclusiveLock);
elog(ERROR, "RemoveType: type '%s' does not exist", typeName); elog(ERROR, "RemoveType: type '%s' does not exist", shadow_type);
} }
typeOid = tup->t_data->t_oid;
heap_delete(relation, &tup->t_self, NULL); 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 #endif
relation = heap_openr(ProcedureRelationName); relation = heap_openr(ProcedureRelationName, RowExclusiveLock);
tup = SearchSysCacheTuple(PRONAME, tup = SearchSysCacheTuple(PRONAME,
PointerGetDatum(functionName), PointerGetDatum(functionName),
Int32GetDatum(nargs), Int32GetDatum(nargs),
@ -337,19 +337,19 @@ RemoveFunction(char *functionName, /* function name to be removed */
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
{ {
heap_close(relation); heap_close(relation, RowExclusiveLock);
func_error("RemoveFunction", functionName, nargs, argList, NULL); func_error("RemoveFunction", functionName, nargs, argList, NULL);
} }
if ((((Form_pg_proc) GETSTRUCT(tup))->prolang) == INTERNALlanguageId) if ((((Form_pg_proc) GETSTRUCT(tup))->prolang) == INTERNALlanguageId)
{ {
heap_close(relation); heap_close(relation, RowExclusiveLock);
elog(ERROR, "RemoveFunction: function \"%s\" is built-in", functionName); elog(ERROR, "RemoveFunction: function \"%s\" is built-in", functionName);
} }
heap_delete(relation, &tup->t_self, NULL); heap_delete(relation, &tup->t_self, NULL);
heap_close(relation); heap_close(relation, RowExclusiveLock);
} }
void void
@ -398,7 +398,7 @@ RemoveAggregate(char *aggName, char *aggType)
} }
#endif #endif
relation = heap_openr(AggregateRelationName); relation = heap_openr(AggregateRelationName, RowExclusiveLock);
tup = SearchSysCacheTuple(AGGNAME, tup = SearchSysCacheTuple(AGGNAME,
PointerGetDatum(aggName), PointerGetDatum(aggName),
ObjectIdGetDatum(basetypeID), ObjectIdGetDatum(basetypeID),
@ -406,7 +406,7 @@ RemoveAggregate(char *aggName, char *aggType)
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
{ {
heap_close(relation); heap_close(relation, RowExclusiveLock);
if (aggType) if (aggType)
{ {
elog(ERROR, "RemoveAggregate: aggregate '%s' for '%s' does not exist", 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_delete(relation, &tup->t_self, NULL);
heap_close(relation); heap_close(relation, RowExclusiveLock);
} }

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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, char *userName,
int recurse) int recurse)
{ {
Relation targetrelation;
Relation attrelation; Relation attrelation;
HeapTuple reltup, HeapTuple reltup,
oldatttup, oldatttup,
@ -71,6 +72,14 @@ renameatt(char *relname,
relname); relname);
#endif #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 * 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 * attribute in all classes that inherit from 'relname' (as well as in
@ -82,16 +91,11 @@ renameatt(char *relname,
*/ */
if (recurse) if (recurse)
{ {
Oid myrelid,
childrelid;
List *child, List *child,
*children; *children;
if ((myrelid = RelnameFindRelid(relname)) == InvalidOid)
elog(ERROR, "renameatt: unknown relation: \"%s\"", relname);
/* this routine is actually in the planner */ /* 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 * find_all_inheritors does the recursive search of the
@ -100,10 +104,11 @@ renameatt(char *relname,
*/ */
foreach(child, children) foreach(child, children)
{ {
Oid childrelid;
char childname[NAMEDATALEN]; char childname[NAMEDATALEN];
childrelid = lfirsti(child); childrelid = lfirsti(child);
if (childrelid == myrelid) if (childrelid == relid)
continue; continue;
reltup = SearchSysCacheTuple(RELOID, reltup = SearchSysCacheTuple(RELOID,
ObjectIdGetDatum(childrelid), ObjectIdGetDatum(childrelid),
@ -117,14 +122,12 @@ renameatt(char *relname,
StrNCpy(childname, StrNCpy(childname,
((Form_pg_class) GETSTRUCT(reltup))->relname.data, ((Form_pg_class) GETSTRUCT(reltup))->relname.data,
NAMEDATALEN); NAMEDATALEN);
/* no more recursion! */ /* note we need not recurse again! */
renameatt(childname, oldattname, newattname, userName, 0); renameatt(childname, oldattname, newattname, userName, 0);
} }
} }
attrelation = heap_openr(AttributeRelationName, RowExclusiveLock);
if ((relid = RelnameFindRelid(relname)) == InvalidOid)
elog(ERROR, "renameatt: relation \"%s\" nonexistent", relname);
oldatttup = SearchSysCacheTupleCopy(ATTNAME, oldatttup = SearchSysCacheTupleCopy(ATTNAME,
ObjectIdGetDatum(relid), ObjectIdGetDatum(relid),
@ -150,7 +153,6 @@ renameatt(char *relname,
StrNCpy((((Form_pg_attribute) (GETSTRUCT(oldatttup)))->attname.data), StrNCpy((((Form_pg_attribute) (GETSTRUCT(oldatttup)))->attname.data),
newattname, NAMEDATALEN); newattname, NAMEDATALEN);
attrelation = heap_openr(AttributeRelationName);
heap_replace(attrelation, &oldatttup->t_self, oldatttup, NULL); heap_replace(attrelation, &oldatttup->t_self, oldatttup, NULL);
/* keep system catalog indices current */ /* keep system catalog indices current */
@ -159,7 +161,7 @@ renameatt(char *relname,
CatalogCloseIndices(Num_pg_attr_indices, irelations); CatalogCloseIndices(Num_pg_attr_indices, irelations);
pfree(oldatttup); pfree(oldatttup);
heap_close(attrelation); heap_close(attrelation, RowExclusiveLock);
} }
/* /*
@ -182,6 +184,7 @@ void
renamerel(char *oldrelname, char *newrelname) renamerel(char *oldrelname, char *newrelname)
{ {
int i; int i;
Relation targetrelation;
Relation relrelation; /* for RELATION relation */ Relation relrelation; /* for RELATION relation */
HeapTuple oldreltup; HeapTuple oldreltup;
char oldpath[MAXPGPATH], 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", elog(ERROR, "renamerel: Illegal class name: \"%s\" -- pg_ is reserved for system catalogs",
newrelname); 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, oldreltup = SearchSysCacheTupleCopy(RELNAME,
PointerGetDatum(oldrelname), PointerGetDatum(oldrelname),
0, 0, 0); 0, 0, 0);
@ -207,12 +219,17 @@ renamerel(char *oldrelname, char *newrelname)
if (RelnameFindRelid(newrelname) != InvalidOid) if (RelnameFindRelid(newrelname) != InvalidOid)
elog(ERROR, "renamerel: relation \"%s\" exists", newrelname); 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 */ /* rename the path first, so if this fails the rename's not done */
strcpy(oldpath, relpath(oldrelname)); strcpy(oldpath, relpath(oldrelname));
strcpy(newpath, relpath(newrelname)); strcpy(newpath, relpath(newrelname));
if (rename(oldpath, newpath) < 0) if (rename(oldpath, newpath) < 0)
elog(ERROR, "renamerel: unable to rename file: %s", oldpath); elog(ERROR, "renamerel: unable to rename file: %s", oldpath);
/* rename additional segments of relation, too */
for (i = 1;; i++) for (i = 1;; i++)
{ {
sprintf(toldpath, "%s.%d", oldpath, i); sprintf(toldpath, "%s.%d", oldpath, i);
@ -225,7 +242,6 @@ renamerel(char *oldrelname, char *newrelname)
newrelname, NAMEDATALEN); newrelname, NAMEDATALEN);
/* insert fixed rel tuple */ /* insert fixed rel tuple */
relrelation = heap_openr(RelationRelationName);
heap_replace(relrelation, &oldreltup->t_self, oldreltup, NULL); heap_replace(relrelation, &oldreltup->t_self, oldreltup, NULL);
/* keep the system catalog indices current */ /* keep the system catalog indices current */
@ -233,5 +249,5 @@ renamerel(char *oldrelname, char *newrelname)
CatalogIndexInsert(irelations, Num_pg_class_indices, relrelation, oldreltup); CatalogIndexInsert(irelations, Num_pg_class_indices, relrelation, oldreltup);
CatalogCloseIndices(Num_pg_class_indices, irelations); CatalogCloseIndices(Num_pg_class_indices, irelations);
heap_close(relrelation); heap_close(relrelation, RowExclusiveLock);
} }

View File

@ -153,10 +153,7 @@ DefineSequence(CreateSeqStmt *seq)
DefineRelation(stmt, RELKIND_SEQUENCE); DefineRelation(stmt, RELKIND_SEQUENCE);
rel = heap_openr(seq->seqname); rel = heap_openr(seq->seqname, AccessExclusiveLock);
Assert(RelationIsValid(rel));
LockRelation(rel, AccessExclusiveLock);
tupDesc = RelationGetDescr(rel); tupDesc = RelationGetDescr(rel);
@ -179,11 +176,7 @@ DefineSequence(CreateSeqStmt *seq)
if (WriteBuffer(buf) == STATUS_ERROR) if (WriteBuffer(buf) == STATUS_ERROR)
elog(ERROR, "DefineSequence: WriteBuffer failed"); elog(ERROR, "DefineSequence: WriteBuffer failed");
UnlockRelation(rel, AccessExclusiveLock); heap_close(rel, AccessExclusiveLock);
heap_close(rel);
return;
} }
@ -422,12 +415,7 @@ init_sequence(char *caller, char *name)
temp = elm; temp = elm;
} }
temp->rel = heap_openr(name); temp->rel = heap_openr(name, AccessShareLock);
if (!RelationIsValid(temp->rel))
elog(ERROR, "%s.%s: sequence does not exist", name, caller);
LockRelation(temp->rel, AccessShareLock);
if (temp->rel->rd_rel->relkind != RELKIND_SEQUENCE) if (temp->rel->rd_rel->relkind != RELKIND_SEQUENCE)
elog(ERROR, "%s.%s: %s is not sequence !", name, caller, name); elog(ERROR, "%s.%s: %s is not sequence !", name, caller, name);
@ -453,7 +441,6 @@ init_sequence(char *caller, char *name)
} }
return elm; return elm;
} }
@ -467,20 +454,15 @@ CloseSequences(void)
SeqTable elm; SeqTable elm;
Relation rel; 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 */ if (elm->rel != (Relation) NULL) /* opened in current xact */
{ {
rel = elm->rel; rel = elm->rel;
elm->rel = (Relation) NULL; elm->rel = (Relation) NULL;
UnlockRelation(rel, AccessShareLock); heap_close(rel, AccessShareLock);
heap_close(rel);
} }
elm = elm->next;
} }
return;
} }

View File

@ -63,11 +63,7 @@ CreateTrigger(CreateTrigStmt *stmt)
elog(ERROR, "%s: %s", stmt->relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]); elog(ERROR, "%s: %s", stmt->relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
#endif #endif
rel = heap_openr(stmt->relname); rel = heap_openr(stmt->relname, AccessExclusiveLock);
if (!RelationIsValid(rel))
elog(ERROR, "CreateTrigger: there is no relation %s", stmt->relname);
LockRelation(rel, AccessExclusiveLock);
TRIGGER_CLEAR_TYPE(tgtype); TRIGGER_CLEAR_TYPE(tgtype);
if (stmt->before) if (stmt->before)
@ -103,8 +99,7 @@ CreateTrigger(CreateTrigStmt *stmt)
} }
/* Scan pg_trigger */ /* Scan pg_trigger */
tgrel = heap_openr(TriggerRelationName); tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
LockRelation(tgrel, AccessExclusiveLock);
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid, ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
F_OIDEQ, RelationGetRelid(rel)); F_OIDEQ, RelationGetRelid(rel));
tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key); tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
@ -203,20 +198,19 @@ CreateTrigger(CreateTrigStmt *stmt)
CatalogIndexInsert(idescs, Num_pg_trigger_indices, tgrel, tuple); CatalogIndexInsert(idescs, Num_pg_trigger_indices, tgrel, tuple);
CatalogCloseIndices(Num_pg_trigger_indices, idescs); CatalogCloseIndices(Num_pg_trigger_indices, idescs);
pfree(tuple); pfree(tuple);
UnlockRelation(tgrel, AccessExclusiveLock); heap_close(tgrel, RowExclusiveLock);
heap_close(tgrel);
pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1])); pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1]));
pfree(DatumGetPointer(values[Anum_pg_trigger_tgargs - 1])); pfree(DatumGetPointer(values[Anum_pg_trigger_tgargs - 1]));
/* update pg_class */ /* update pg_class */
pgrel = heap_openr(RelationRelationName, RowExclusiveLock);
tuple = SearchSysCacheTupleCopy(RELNAME, tuple = SearchSysCacheTupleCopy(RELNAME,
PointerGetDatum(stmt->relname), PointerGetDatum(stmt->relname),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
elog(ERROR, "CreateTrigger: relation %s not found in pg_class", stmt->relname); elog(ERROR, "CreateTrigger: relation %s not found in pg_class", stmt->relname);
pgrel = heap_openr(RelationRelationName);
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1; ((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1;
RelationInvalidateHeapTuple(pgrel, tuple); RelationInvalidateHeapTuple(pgrel, tuple);
heap_replace(pgrel, &tuple->t_self, tuple, NULL); heap_replace(pgrel, &tuple->t_self, tuple, NULL);
@ -224,7 +218,7 @@ CreateTrigger(CreateTrigStmt *stmt)
CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple); CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
CatalogCloseIndices(Num_pg_class_indices, ridescs); CatalogCloseIndices(Num_pg_class_indices, ridescs);
pfree(tuple); pfree(tuple);
heap_close(pgrel); heap_close(pgrel, RowExclusiveLock);
CommandCounterIncrement(); CommandCounterIncrement();
oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
@ -232,8 +226,8 @@ CreateTrigger(CreateTrigStmt *stmt)
rel->rd_rel->reltriggers = found + 1; rel->rd_rel->reltriggers = found + 1;
RelationBuildTriggers(rel); RelationBuildTriggers(rel);
MemoryContextSwitchTo(oldcxt); MemoryContextSwitchTo(oldcxt);
heap_close(rel); /* Keep lock on target rel until end of xact */
return; heap_close(rel, NoLock);
} }
void void
@ -255,14 +249,9 @@ DropTrigger(DropTrigStmt *stmt)
elog(ERROR, "%s: %s", stmt->relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]); elog(ERROR, "%s: %s", stmt->relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
#endif #endif
rel = heap_openr(stmt->relname); rel = heap_openr(stmt->relname, AccessExclusiveLock);
if (!RelationIsValid(rel))
elog(ERROR, "DropTrigger: there is no relation %s", stmt->relname);
LockRelation(rel, AccessExclusiveLock); tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
tgrel = heap_openr(TriggerRelationName);
LockRelation(tgrel, AccessExclusiveLock);
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid, ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
F_OIDEQ, RelationGetRelid(rel)); F_OIDEQ, RelationGetRelid(rel));
tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key); 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", elog(ERROR, "DropTrigger: there is no trigger %s on relation %s",
stmt->trigname, stmt->relname); stmt->trigname, stmt->relname);
if (tgfound > 1) 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); tgfound, stmt->trigname, stmt->relname);
heap_endscan(tgscan); heap_endscan(tgscan);
UnlockRelation(tgrel, AccessExclusiveLock); heap_close(tgrel, RowExclusiveLock);
heap_close(tgrel);
/* update pg_class */
pgrel = heap_openr(RelationRelationName, RowExclusiveLock);
tuple = SearchSysCacheTupleCopy(RELNAME, tuple = SearchSysCacheTupleCopy(RELNAME,
PointerGetDatum(stmt->relname), PointerGetDatum(stmt->relname),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
elog(ERROR, "DropTrigger: relation %s not found in pg_class", stmt->relname); 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; ((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found;
RelationInvalidateHeapTuple(pgrel, tuple); RelationInvalidateHeapTuple(pgrel, tuple);
heap_replace(pgrel, &tuple->t_self, tuple, NULL); heap_replace(pgrel, &tuple->t_self, tuple, NULL);
@ -303,7 +291,7 @@ DropTrigger(DropTrigStmt *stmt)
CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple); CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
CatalogCloseIndices(Num_pg_class_indices, ridescs); CatalogCloseIndices(Num_pg_class_indices, ridescs);
pfree(tuple); pfree(tuple);
heap_close(pgrel); heap_close(pgrel, RowExclusiveLock);
CommandCounterIncrement(); CommandCounterIncrement();
oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
@ -312,8 +300,8 @@ DropTrigger(DropTrigStmt *stmt)
if (found > 0) if (found > 0)
RelationBuildTriggers(rel); RelationBuildTriggers(rel);
MemoryContextSwitchTo(oldcxt); MemoryContextSwitchTo(oldcxt);
heap_close(rel); /* Keep lock on target rel until end of xact */
return; heap_close(rel, NoLock);
} }
void void
@ -324,8 +312,7 @@ RelationRemoveTriggers(Relation rel)
ScanKeyData key; ScanKeyData key;
HeapTuple tup; HeapTuple tup;
tgrel = heap_openr(TriggerRelationName); tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
LockRelation(tgrel, AccessExclusiveLock);
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid, ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
F_OIDEQ, RelationGetRelid(rel)); F_OIDEQ, RelationGetRelid(rel));
@ -335,9 +322,7 @@ RelationRemoveTriggers(Relation rel)
heap_delete(tgrel, &tup->t_self, NULL); heap_delete(tgrel, &tup->t_self, NULL);
heap_endscan(tgscan); heap_endscan(tgscan);
UnlockRelation(tgrel, AccessExclusiveLock); heap_close(tgrel, RowExclusiveLock);
heap_close(tgrel);
} }
void void
@ -367,7 +352,7 @@ RelationBuildTriggers(Relation relation)
(RegProcedure) F_OIDEQ, (RegProcedure) F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(relation))); ObjectIdGetDatum(RelationGetRelid(relation)));
tgrel = heap_openr(TriggerRelationName); tgrel = heap_openr(TriggerRelationName, AccessShareLock);
irel = index_openr(TriggerRelidIndex); irel = index_openr(TriggerRelidIndex);
sd = index_beginscan(irel, false, 1, &skey); sd = index_beginscan(irel, false, 1, &skey);
@ -441,7 +426,7 @@ RelationBuildTriggers(Relation relation)
index_endscan(sd); index_endscan(sd);
pfree(sd); pfree(sd);
index_close(irel); index_close(irel);
heap_close(tgrel); heap_close(tgrel, AccessShareLock);
/* Build trigdesc */ /* Build trigdesc */
trigdesc->triggers = triggers; trigdesc->triggers = triggers;

View File

@ -5,7 +5,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * 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 * 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. * 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 static void
void
UpdatePgPwdFile(char *sql, CommandDest dest) UpdatePgPwdFile(char *sql, CommandDest dest)
{ {
char *filename, char *filename,
*tempname; *tempname;
int bufsize; int bufsize;
@ -125,17 +127,13 @@ DefineUser(CreateUserStmt *stmt, CommandDest dest)
/* /*
* Scan the pg_shadow relation to be certain the user doesn't already * 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); 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); scan = heap_beginscan(pg_shadow_rel, false, SnapshotNow, 0, NULL);
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0))) while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
{ {
@ -152,8 +150,7 @@ DefineUser(CreateUserStmt *stmt, CommandDest dest)
if (exists) if (exists)
{ {
UnlockRelation(pg_shadow_rel, AccessExclusiveLock); heap_close(pg_shadow_rel, AccessExclusiveLock);
heap_close(pg_shadow_rel);
UserAbortTransactionBlock(); UserAbortTransactionBlock();
elog(ERROR, elog(ERROR,
"defineUser: user \"%s\" has already been created", stmt->user); "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 * XXX Ugly as this code is, it still fails to cope with ' or \ in any of
* the provided strings. * 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, snprintf(sql, SQL_LENGTH,
"insert into %s (usename,usesysid,usecreatedb,usetrace," "insert into %s (usename,usesysid,usecreatedb,usetrace,"
@ -189,17 +192,21 @@ DefineUser(CreateUserStmt *stmt, CommandDest dest)
pg_exec_query_dest(sql, dest, false); 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); UpdatePgPwdFile(sql, dest);
/* /*
* This goes after the UpdatePgPwdFile to be certain that two backends * Now we can clean up.
* to not attempt to write to the pg_pwd file at the same time.
*/ */
UnlockRelation(pg_shadow_rel, AccessExclusiveLock); heap_close(pg_shadow_rel, AccessExclusiveLock);
heap_close(pg_shadow_rel);
if (IsTransactionBlock() && !inblock) if (IsTransactionBlock() && !inblock)
EndTransactionBlock(); EndTransactionBlock();
@ -237,70 +244,79 @@ AlterUser(AlterUserStmt *stmt, CommandDest dest)
/* /*
* Scan the pg_shadow relation to be certain the user exists. * 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); 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, tuple = SearchSysCacheTuple(USENAME,
PointerGetDatum(stmt->user), PointerGetDatum(stmt->user),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
{ {
UnlockRelation(pg_shadow_rel, AccessExclusiveLock); heap_close(pg_shadow_rel, AccessExclusiveLock);
heap_close(pg_shadow_rel); UserAbortTransactionBlock();
UserAbortTransactionBlock(); /* needed? */
elog(ERROR, "alterUser: user \"%s\" does not exist", stmt->user); elog(ERROR, "alterUser: user \"%s\" does not exist", stmt->user);
return;
} }
/* /*
* Create the update statement to modify the user. * 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); snprintf(sql, SQL_LENGTH, "update %s set", ShadowRelationName);
if (stmt->password) 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) if (stmt->createdb)
{ {
snprintf(sql, SQL_LENGTH, "%s %susecreatedb='%s'", snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql),
pstrdup(sql), stmt->password ? "," : "", "%s usecreatedb='%s'",
stmt->password ? "," : "",
*stmt->createdb ? "t" : "f"); *stmt->createdb ? "t" : "f");
} }
if (stmt->createuser) if (stmt->createuser)
{ {
snprintf(sql, SQL_LENGTH, "%s %susesuper='%s'", snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql),
pstrdup(sql), (stmt->password || stmt->createdb) ? "," : "", "%s usesuper='%s'",
(stmt->password || stmt->createdb) ? "," : "",
*stmt->createuser ? "t" : "f"); *stmt->createuser ? "t" : "f");
} }
if (stmt->validUntil) if (stmt->validUntil)
{ {
snprintf(sql, SQL_LENGTH, "%s %svaluntil='%s'", snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql),
pstrdup(sql), "%s valuntil='%s'",
(stmt->password || stmt->createdb || stmt->createuser) ? "," : "", (stmt->password || stmt->createdb || stmt->createuser) ? "," : "",
stmt->validUntil); stmt->validUntil);
} }
snprintf(sql, SQL_LENGTH, "%s where usename = '%s'", snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql),
pstrdup(sql), stmt->user); " where usename = '%s'",
stmt->user);
pg_exec_query_dest(sql, dest, false); 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); 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) if (IsTransactionBlock() && !inblock)
EndTransactionBlock(); EndTransactionBlock();
@ -310,7 +326,6 @@ AlterUser(AlterUserStmt *stmt, CommandDest dest)
extern void extern void
RemoveUser(char *user, CommandDest dest) RemoveUser(char *user, CommandDest dest)
{ {
char *pg_shadow; char *pg_shadow;
Relation pg_shadow_rel, Relation pg_shadow_rel,
pg_rel; pg_rel;
@ -318,7 +333,7 @@ RemoveUser(char *user, CommandDest dest)
HeapScanDesc scan; HeapScanDesc scan;
HeapTuple tuple; HeapTuple tuple;
Datum datum; Datum datum;
char sql[512]; char sql[SQL_LENGTH];
bool n, bool n,
inblock; inblock;
int32 usesysid; int32 usesysid;
@ -341,27 +356,19 @@ RemoveUser(char *user, CommandDest dest)
} }
/* /*
* Perform a scan of the pg_shadow relation to find the usesysid of * Scan the pg_shadow relation to find the usesysid of the user to be
* the user to be deleted. If it is not found, then return a warning * deleted. Note we secure exclusive lock, because we need to protect
* message. * 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); 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, tuple = SearchSysCacheTuple(USENAME,
PointerGetDatum(user), PointerGetDatum(user),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
{ {
UnlockRelation(pg_shadow_rel, AccessExclusiveLock); heap_close(pg_shadow_rel, AccessExclusiveLock);
heap_close(pg_shadow_rel);
UserAbortTransactionBlock(); UserAbortTransactionBlock();
elog(ERROR, "removeUser: user \"%s\" does not exist", user); 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 * Perform a scan of the pg_database relation to find the databases
* owned by usesysid. Then drop them. * owned by usesysid. Then drop them.
*/ */
pg_rel = heap_openr(DatabaseRelationName); pg_rel = heap_openr(DatabaseRelationName, AccessExclusiveLock);
pg_dsc = RelationGetDescr(pg_rel); pg_dsc = RelationGetDescr(pg_rel);
scan = heap_beginscan(pg_rel, false, SnapshotNow, 0, NULL); scan = heap_beginscan(pg_rel, false, SnapshotNow, 0, NULL);
@ -383,7 +390,7 @@ RemoveUser(char *user, CommandDest dest)
if ((int) datum == usesysid) if ((int) datum == usesysid)
{ {
datum = heap_getattr(tuple, Anum_pg_database_datname, pg_dsc, &n); 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 = dbase =
(char **) repalloc((void *) dbase, sizeof(char *) * (ndbase + 1)); (char **) repalloc((void *) dbase, sizeof(char *) * (ndbase + 1));
@ -394,12 +401,12 @@ RemoveUser(char *user, CommandDest dest)
} }
} }
heap_endscan(scan); heap_endscan(scan);
heap_close(pg_rel); heap_close(pg_rel, AccessExclusiveLock);
while (ndbase--) while (ndbase--)
{ {
elog(NOTICE, "Dropping database %s", dbase[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]); pfree((void *) dbase[ndbase]);
pg_exec_query_dest(sql, dest, false); pg_exec_query_dest(sql, dest, false);
} }
@ -431,10 +438,18 @@ RemoveUser(char *user, CommandDest dest)
"delete from %s where usename = '%s'", ShadowRelationName, user); "delete from %s where usename = '%s'", ShadowRelationName, user);
pg_exec_query_dest(sql, dest, false); 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); 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) if (IsTransactionBlock() && !inblock)
EndTransactionBlock(); EndTransactionBlock();

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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); portalmem = PortalGetVariableMemory(vc_portal);
vrl = cur = (VRelList) NULL; vrl = cur = (VRelList) NULL;
rel = heap_openr(RelationRelationName); rel = heap_openr(RelationRelationName, AccessShareLock);
tupdesc = RelationGetDescr(rel); tupdesc = RelationGetDescr(rel);
scan = heap_beginscan(rel, false, SnapshotNow, 1, &key); scan = heap_beginscan(rel, false, SnapshotNow, 1, &key);
@ -343,9 +343,8 @@ vc_getrels(NameData *VacRelP)
if (found == false) if (found == false)
elog(NOTICE, "Vacuum: table not found"); elog(NOTICE, "Vacuum: table not found");
heap_endscan(scan); heap_endscan(scan);
heap_close(rel); heap_close(rel, AccessShareLock);
CommitTransactionCommand(); CommitTransactionCommand();
@ -395,8 +394,10 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
return; 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 = (VRelStats *) palloc(sizeof(VRelStats));
vacrelstats->relid = relid; vacrelstats->relid = relid;
@ -509,9 +510,6 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
vacrelstats->vacattrstats = (VacAttrStats *) NULL; vacrelstats->vacattrstats = (VacAttrStats *) NULL;
} }
/* we require the relation to be locked until the indices are cleaned */
LockRelation(onerel, AccessExclusiveLock);
GetXmaxRecent(&XmaxRecent); GetXmaxRecent(&XmaxRecent);
/* scan it */ /* scan it */
@ -565,13 +563,13 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
pfree(fraged_pages.vpl_pagedesc); pfree(fraged_pages.vpl_pagedesc);
} }
/* all done with this class */
heap_close(onerel);
/* update statistics in pg_class */ /* update statistics in pg_class */
vc_updstats(vacrelstats->relid, vacrelstats->num_pages, vc_updstats(vacrelstats->relid, vacrelstats->num_pages,
vacrelstats->num_tuples, vacrelstats->hasindex, vacrelstats); 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 */ /* next command frees attribute stats */
CommitTransactionCommand(); 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 * update number of tuples and number of pages in pg_class
*/ */
rd = heap_openr(RelationRelationName, RowExclusiveLock);
ctup = SearchSysCacheTupleCopy(RELOID, ctup = SearchSysCacheTupleCopy(RELOID,
ObjectIdGetDatum(relid), ObjectIdGetDatum(relid),
0, 0, 0); 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", elog(ERROR, "pg_class entry for relid %u vanished during vacuuming",
relid); relid);
rd = heap_openr(RelationRelationName);
/* get the buffer cache tuple */ /* get the buffer cache tuple */
rtup.t_self = ctup->t_self; rtup.t_self = ctup->t_self;
heap_fetch(rd, SnapshotNow, &rtup, &buffer); 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; VacAttrStats *vacattrstats = vacrelstats->vacattrstats;
int natts = vacrelstats->va_natts; int natts = vacrelstats->va_natts;
ad = heap_openr(AttributeRelationName); ad = heap_openr(AttributeRelationName, RowExclusiveLock);
sd = heap_openr(StatisticRelationName); sd = heap_openr(StatisticRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&askey, 0, Anum_pg_attribute_attrelid, ScanKeyEntryInitialize(&askey, 0, Anum_pg_attribute_attrelid,
F_INT4EQ, relid); F_INT4EQ, relid);
@ -2458,8 +2456,8 @@ vc_updstats(Oid relid, int num_pages, int num_tuples, bool hasindex, VRelStats *
} }
} }
heap_endscan(scan); heap_endscan(scan);
heap_close(ad); heap_close(ad, RowExclusiveLock);
heap_close(sd); heap_close(sd, RowExclusiveLock);
} }
/* /*
@ -2469,7 +2467,7 @@ vc_updstats(Oid relid, int num_pages, int num_tuples, bool hasindex, VRelStats *
WriteBuffer(buffer); WriteBuffer(buffer);
heap_close(rd); heap_close(rd, RowExclusiveLock);
} }
/* /*
@ -2484,7 +2482,7 @@ vc_delhilowstats(Oid relid, int attcnt, int *attnums)
HeapTuple tuple; HeapTuple tuple;
ScanKeyData key; ScanKeyData key;
pgstatistic = heap_openr(StatisticRelationName); pgstatistic = heap_openr(StatisticRelationName, RowExclusiveLock);
if (relid != InvalidOid) if (relid != InvalidOid)
{ {
@ -2515,7 +2513,7 @@ vc_delhilowstats(Oid relid, int attcnt, int *attnums)
} }
heap_endscan(scan); 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)); ioid = (Oid *) palloc(10 * sizeof(Oid));
/* prepare a heap scan on the pg_index relation */ /* prepare a heap scan on the pg_index relation */
pgindex = heap_openr(IndexRelationName); pgindex = heap_openr(IndexRelationName, AccessShareLock);
tupdesc = RelationGetDescr(pgindex); tupdesc = RelationGetDescr(pgindex);
ScanKeyEntryInitialize(&key, 0x0, Anum_pg_index_indrelid, ScanKeyEntryInitialize(&key, 0x0, Anum_pg_index_indrelid,
@ -2741,7 +2739,7 @@ vc_getindices(Oid relid, int *nindices, Relation **Irel)
} }
heap_endscan(scan); heap_endscan(scan);
heap_close(pgindex); heap_close(pgindex, AccessShareLock);
if (i == 0) if (i == 0)
{ /* No one index found */ { /* No one index found */

View File

@ -1,11 +1,11 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* execAmi.c * execAmi.c
* miscellanious executor access method routines * miscellaneous executor access method routines
* *
* Copyright (c) 1994, Regents of the University of California * 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, static Pointer ExecBeginScan(Relation relation, int nkeys, ScanKey skeys,
bool isindex, ScanDirection dir, Snapshot snapshot); bool isindex, ScanDirection dir, Snapshot snapshot);
static Relation ExecOpenR(Oid relationOid, bool isindex);
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecOpenScanR * ExecOpenScanR
@ -90,7 +89,22 @@ ExecOpenScanR(Oid relOid,
* abstraction someday -cim 9/9/89 * abstraction someday -cim 9/9/89
* ---------------- * ----------------
*/ */
relation = ExecOpenR(relOid, isindex);
/* ----------------
* 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(relOid);
else
relation = heap_open(relOid, NoLock);
if (relation == NULL)
elog(ERROR, "ExecOpenScanR: failed to open relation %u", relOid);
scanDesc = ExecBeginScan(relation, scanDesc = ExecBeginScan(relation,
nkeys, nkeys,
skeys, skeys,
@ -104,35 +118,6 @@ ExecOpenScanR(Oid relOid,
*returnScanDesc = scanDesc; *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.
* ----------------
*/
if (isindex)
relation = index_open(relationOid);
else
relation = heap_open(relationOid);
if (relation == NULL)
elog(DEBUG, "ExecOpenR: relation == NULL, heap_open failed.");
return relation;
}
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecBeginScan * ExecBeginScan
* *
@ -243,15 +228,20 @@ ExecCloseR(Plan *node)
if (scanDesc != NULL) if (scanDesc != NULL)
heap_endscan(scanDesc); 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) if (relation != NULL)
heap_close(relation); heap_close(relation, NoLock);
/* ---------------- /* ----------------
* if this is an index scan then we have to take care * if this is an index scan then we have to take care
* of the index relations as well.. * of the index relations as well..
* ---------------- * ----------------
*/ */
if (nodeTag(node) == T_IndexScan) if (IsA(node, IndexScan))
{ {
IndexScan *iscan = (IndexScan *) node; IndexScan *iscan = (IndexScan *) node;
IndexScanState *indexstate; IndexScanState *indexstate;

View File

@ -26,7 +26,7 @@
* *
* *
* IDENTIFICATION * 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; resultRelationIndex = resultRelation;
rtentry = rt_fetch(resultRelationIndex, rangeTable); rtentry = rt_fetch(resultRelationIndex, rangeTable);
resultRelationOid = rtentry->relid; resultRelationOid = rtentry->relid;
resultRelationDesc = heap_open(resultRelationOid); resultRelationDesc = heap_open(resultRelationOid, RowExclusiveLock);
if (resultRelationDesc->rd_rel->relkind == RELKIND_SEQUENCE) if (resultRelationDesc->rd_rel->relkind == RELKIND_SEQUENCE)
elog(ERROR, "You can't change sequence relation %s", elog(ERROR, "You can't change sequence relation %s",
resultRelationDesc->rd_rel->relname.data); resultRelationDesc->rd_rel->relname.data);
LockRelation(resultRelationDesc, RowExclusiveLock);
resultRelationInfo = makeNode(RelationInfo); resultRelationInfo = makeNode(RelationInfo);
resultRelationInfo->ri_RangeTableIndex = resultRelationIndex; resultRelationInfo->ri_RangeTableIndex = resultRelationIndex;
resultRelationInfo->ri_RelationDesc = resultRelationDesc; resultRelationInfo->ri_RelationDesc = resultRelationDesc;
@ -636,8 +634,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
{ {
rm = lfirst(l); rm = lfirst(l);
relid = ((RangeTblEntry *) nth(rm->rti - 1, rangeTable))->relid; relid = ((RangeTblEntry *) nth(rm->rti - 1, rangeTable))->relid;
relation = heap_open(relid); relation = heap_open(relid, RowShareLock);
LockRelation(relation, RowShareLock);
if (!(rm->info & ROW_MARK_FOR_UPDATE)) if (!(rm->info & ROW_MARK_FOR_UPDATE))
continue; continue;
erm = (execRowMark *) palloc(sizeof(execRowMark)); erm = (execRowMark *) palloc(sizeof(execRowMark));
@ -758,7 +755,8 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
*/ */
setheapoverride(true); setheapoverride(true);
intoRelationDesc = heap_open(intoRelationId); intoRelationDesc = heap_open(intoRelationId,
AccessExclusiveLock);
setheapoverride(false); 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) if (resultRelationInfo != NULL)
{ {
Relation resultRelationDesc; Relation resultRelationDesc;
resultRelationDesc = resultRelationInfo->ri_RelationDesc; resultRelationDesc = resultRelationInfo->ri_RelationDesc;
heap_close(resultRelationDesc); heap_close(resultRelationDesc, NoLock);
/* /*
* close indices on the result relation * close indices on the result relation
@ -828,7 +827,7 @@ EndPlan(Plan *plan, EState *estate)
* close the "into" relation if necessary * close the "into" relation if necessary
*/ */
if (intoRelationDesc != NULL) if (intoRelationDesc != NULL)
heap_close(intoRelationDesc); heap_close(intoRelationDesc, NoLock);
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 * open pg_index
* ---------------- * ----------------
*/ */
indexRd = heap_openr(IndexRelationName); indexRd = heap_openr(IndexRelationName, AccessShareLock);
/* ---------------- /* ----------------
* form a scan key * form a scan key
@ -856,7 +856,7 @@ ExecOpenIndices(Oid resultRelationOid,
* ---------------- * ----------------
*/ */
heap_endscan(indexSd); heap_endscan(indexSd);
heap_close(indexRd); heap_close(indexRd, AccessShareLock);
/* ---------------- /* ----------------
* Now that we've collected the index information into three * 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 * 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 * not ready for MVCC) and so we have to exclusively lock
* indices here to prevent deadlocks if we will scan them * indices here to prevent deadlocks if we will scan them
* - index_beginscan places AccessShareLock, indices * - index_beginscan places AccessShareLock, indices
@ -1010,7 +1010,7 @@ ExecCloseIndices(RelationInfo *resultRelationInfo)
continue; continue;
/* /*
* Notes in ExecOpenIndices. * See notes in ExecOpenIndices.
*/ */
if (relationDescs[i]->rd_rel->relam != BTREE_AM_OID && if (relationDescs[i]->rd_rel->relam != BTREE_AM_OID &&
relationDescs[i]->rd_rel->relam != HASH_AM_OID) relationDescs[i]->rd_rel->relam != HASH_AM_OID)

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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; reloid = rtentry->relid;
rri = makeNode(RelationInfo); rri = makeNode(RelationInfo);
rri->ri_RangeTableIndex = es_rri->ri_RangeTableIndex; 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_NumIndices = 0;
rri->ri_IndexRelationDescs = NULL; /* index descs */ rri->ri_IndexRelationDescs = NULL; /* index descs */
rri->ri_IndexRelationInfo = NULL; /* index key info */ rri->ri_IndexRelationInfo = NULL; /* index key info */
@ -484,7 +484,7 @@ ExecEndAppend(Append *node)
resultRelationInfo = (RelationInfo *) lfirst(resultRelationInfoList); resultRelationInfo = (RelationInfo *) lfirst(resultRelationInfoList);
resultRelationDesc = resultRelationInfo->ri_RelationDesc; resultRelationDesc = resultRelationInfo->ri_RelationDesc;
heap_close(resultRelationDesc); heap_close(resultRelationDesc, NoLock);
pfree(resultRelationInfo); pfree(resultRelationInfo);
resultRelationInfoList = lnext(resultRelationInfoList); resultRelationInfoList = lnext(resultRelationInfoList);
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, F_OIDEQ,
ObjectIdGetDatum(pred_op)); ObjectIdGetDatum(pred_op));
relation = heap_openr(AccessMethodOperatorRelationName); relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock);
/* /*
* The following assumes that any given operator will only be in a * 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)) if (!HeapTupleIsValid(tuple))
{ {
elog(DEBUG, "clause_pred_clause_test: unknown pred_op"); elog(DEBUG, "clause_pred_clause_test: unknown pred_op");
heap_endscan(scan);
heap_close(relation, AccessShareLock);
return false; return false;
} }
aform = (Form_pg_amop) GETSTRUCT(tuple); aform = (Form_pg_amop) GETSTRUCT(tuple);
@ -1209,6 +1211,8 @@ clause_pred_clause_test(Expr *predicate, Node *clause)
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
{ {
elog(DEBUG, "clause_pred_clause_test: unknown clause_op"); elog(DEBUG, "clause_pred_clause_test: unknown clause_op");
heap_endscan(scan);
heap_close(relation, AccessShareLock);
return false; return false;
} }
aform = (Form_pg_amop) GETSTRUCT(tuple); 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]; test_strategy = BT_implic_table[clause_strategy - 1][pred_strategy - 1];
if (test_strategy == 0) if (test_strategy == 0)
{
heap_close(relation, AccessShareLock);
return false; /* the implication cannot be determined */ return false; /* the implication cannot be determined */
}
/* /*
* 4. From the same opclass, find the operator for the test strategy * 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)) if (!HeapTupleIsValid(tuple))
{ {
elog(DEBUG, "clause_pred_clause_test: unknown test_op"); elog(DEBUG, "clause_pred_clause_test: unknown test_op");
heap_endscan(scan);
heap_close(relation, AccessShareLock);
return false; return false;
} }
aform = (Form_pg_amop) GETSTRUCT(tuple); aform = (Form_pg_amop) GETSTRUCT(tuple);
/* Get the test operator */ /* Get the test operator */
test_op = aform->amopopr; test_op = aform->amopopr;
heap_endscan(scan); heap_endscan(scan);
heap_close(relation, AccessShareLock);
/* /*
* 5. Evaluate the test * 5. Evaluate the test

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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; Resdom *resnode;
Relation reln; Relation reln;
Oid relid; Oid relid;
Oid tletype;
int relnatts; int relnatts;
int i; int i;
@ -713,11 +712,7 @@ pg_checkretval(Oid rettype, List *queryTreeList)
* declared return type, and be sure that attributes 1 .. n in the * declared return type, and be sure that attributes 1 .. n in the
* target list match the declared types. * target list match the declared types.
*/ */
reln = heap_open(typeTypeRelid(typ)); reln = heap_open(typeTypeRelid(typ), AccessShareLock);
if (!RelationIsValid(reln))
elog(ERROR, "cannot open relation relid %u", typeTypeRelid(typ));
relid = reln->rd_id; relid = reln->rd_id;
relnatts = reln->rd_rel->relnatts; relnatts = reln->rd_rel->relnatts;
@ -729,41 +724,12 @@ pg_checkretval(Oid rettype, List *queryTreeList)
{ {
TargetEntry *tle = lfirst(tlist); TargetEntry *tle = lfirst(tlist);
Node *thenode = tle->expr; 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) 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)); elog(ERROR, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ));
tlist = lnext(tlist);
} }
heap_close(reln); heap_close(reln, AccessShareLock);
/* success */
return;
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 */ /* Find an index on the given relation */
if (first) if (first)
{ {
if (RelationIsValid(relation))
heap_close(relation);
if (HeapScanIsValid(scan)) if (HeapScanIsValid(scan))
heap_endscan(scan); heap_endscan(scan);
scan = (HeapScanDesc) NULL;
if (RelationIsValid(relation))
heap_close(relation, AccessShareLock);
relation = (Relation) NULL;
ScanKeyEntryInitialize(&indexKey, 0, ScanKeyEntryInitialize(&indexKey, 0,
Anum_pg_index_indrelid, Anum_pg_index_indrelid,
F_OIDEQ, F_OIDEQ,
ObjectIdGetDatum(indrelid)); ObjectIdGetDatum(indrelid));
relation = heap_openr(IndexRelationName); relation = heap_openr(IndexRelationName, AccessShareLock);
scan = heap_beginscan(relation, 0, SnapshotNow, scan = heap_beginscan(relation, 0, SnapshotNow,
1, &indexKey); 1, &indexKey);
} }
@ -146,7 +148,7 @@ index_info(Query *root, bool first, int relid, IdxInfoRetval *info)
if (!HeapTupleIsValid(indexTuple)) if (!HeapTupleIsValid(indexTuple))
{ {
heap_endscan(scan); heap_endscan(scan);
heap_close(relation); heap_close(relation, AccessShareLock);
scan = (HeapScanDesc) NULL; scan = (HeapScanDesc) NULL;
relation = (Relation) NULL; relation = (Relation) NULL;
return 0; return 0;
@ -190,7 +192,7 @@ index_info(Query *root, bool first, int relid, IdxInfoRetval *info)
info->relam = relam; info->relam = relam;
info->pages = indexRelation->rd_rel->relpages; info->pages = indexRelation->rd_rel->relpages;
info->tuples = indexRelation->rd_rel->reltuples; info->tuples = indexRelation->rd_rel->reltuples;
heap_close(indexRelation); index_close(indexRelation);
/* /*
* Find the index ordering keys * 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_nargs = key[0].sk_func.fn_nargs;
key[0].sk_argument = ObjectIdGetDatum((Oid) inhparent); key[0].sk_argument = ObjectIdGetDatum((Oid) inhparent);
relation = heap_openr(InheritsRelationName); relation = heap_openr(InheritsRelationName, AccessShareLock);
scan = heap_beginscan(relation, 0, SnapshotNow, 1, key); scan = heap_beginscan(relation, 0, SnapshotNow, 1, key);
while (HeapTupleIsValid(inheritsTuple = heap_getnext(scan, 0))) while (HeapTupleIsValid(inheritsTuple = heap_getnext(scan, 0)))
{ {
@ -398,7 +400,7 @@ find_inheritance_children(Oid inhparent)
list = lappendi(list, inhrelid); list = lappendi(list, inhrelid);
} }
heap_endscan(scan); heap_endscan(scan);
heap_close(relation); heap_close(relation, AccessShareLock);
return list; return list;
} }
@ -424,8 +426,8 @@ VersionGetParents(Oid verrelid)
fmgr_info(F_OIDEQ, &key[0].sk_func); fmgr_info(F_OIDEQ, &key[0].sk_func);
key[0].sk_nargs = key[0].sk_func.fn_nargs; key[0].sk_nargs = key[0].sk_func.fn_nargs;
relation = heap_openr(VersionRelationName);
key[0].sk_argument = ObjectIdGetDatum(verrelid); key[0].sk_argument = ObjectIdGetDatum(verrelid);
relation = heap_openr(VersionRelationName, AccessShareLock);
scan = heap_beginscan(relation, 0, SnapshotNow, 1, key); scan = heap_beginscan(relation, 0, SnapshotNow, 1, key);
while (HeapTupleIsValid(versionTuple = heap_getnext(scan, 0))) while (HeapTupleIsValid(versionTuple = heap_getnext(scan, 0)))
{ {
@ -438,7 +440,7 @@ VersionGetParents(Oid verrelid)
heap_rescan(scan, 0, key); heap_rescan(scan, 0, key);
} }
heap_endscan(scan); heap_endscan(scan);
heap_close(relation); heap_close(relation, AccessShareLock);
return list; return list;
} }

View File

@ -5,7 +5,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * 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)); parsetree = transformStmt(pstate, lfirst(pl));
if (pstate->p_target_relation != NULL) 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_relation = NULL;
pstate->p_target_rangetblentry = NULL; pstate->p_target_rangetblentry = NULL;
@ -73,7 +73,7 @@ parse_analyze(List *pl, ParseState *parentParseState)
result = lappend(result, result = lappend(result,
transformStmt(pstate, lfirst(extras_before))); transformStmt(pstate, lfirst(extras_before)));
if (pstate->p_target_relation != NULL) 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_relation = NULL;
pstate->p_target_rangetblentry = NULL; pstate->p_target_rangetblentry = NULL;
extras_before = lnext(extras_before); extras_before = lnext(extras_before);
@ -86,7 +86,7 @@ parse_analyze(List *pl, ParseState *parentParseState)
result = lappend(result, result = lappend(result,
transformStmt(pstate, lfirst(extras_after))); transformStmt(pstate, lfirst(extras_after)));
if (pstate->p_target_relation != NULL) 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_relation = NULL;
pstate->p_target_rangetblentry = NULL; pstate->p_target_rangetblentry = NULL;
extras_after = lnext(extras_after); extras_after = lnext(extras_after);

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 */ /* This could only happen for multi-action rules */
if (pstate->p_target_relation != NULL) 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_rangetblentry = rte;
pstate->p_target_relation = heap_open(rte->relid); pstate->p_target_relation = heap_open(rte->relid, AccessShareLock);
/* will close relation later */ /* will close relation later, see analyze.c */
} }
/* /*

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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); fmgr_info(F_NAMEEQ, (FmgrInfo *) &aggKey[0].sk_func);
aggKey[0].sk_argument = NameGetDatum(aggname); 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, pg_aggregate_scan = heap_beginscan(pg_aggregate_desc,
0, 0,
SnapshotSelf, /* ??? */ SnapshotSelf, /* ??? */
@ -159,7 +159,7 @@ agg_get_candidates(char *aggname,
} }
heap_endscan(pg_aggregate_scan); heap_endscan(pg_aggregate_scan);
heap_close(pg_aggregate_desc); heap_close(pg_aggregate_desc, AccessShareLock);
return ncandidates; return ncandidates;
} /* agg_get_candidates() */ } /* agg_get_candidates() */
@ -310,11 +310,11 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
if (attisset) if (attisset)
{ {
toid = exprType(first_arg); toid = exprType(first_arg);
rd = heap_openr(typeidTypeName(toid)); rd = heap_openr(typeidTypeName(toid), NoLock);
if (RelationIsValid(rd)) if (RelationIsValid(rd))
{ {
relname = RelationGetRelationName(rd)->data; relname = RelationGetRelationName(rd)->data;
heap_close(rd); heap_close(rd, NoLock);
} }
else else
elog(ERROR, "Type '%s' is not a relation type", elog(ERROR, "Type '%s' is not a relation type",
@ -646,7 +646,7 @@ func_get_candidates(char *funcname, int nargs)
CandidateList current_candidate; CandidateList current_candidate;
int i; int i;
heapRelation = heap_openr(ProcedureRelationName); heapRelation = heap_openr(ProcedureRelationName, AccessShareLock);
ScanKeyEntryInitialize(&skey, ScanKeyEntryInitialize(&skey,
(bits16) 0x0, (bits16) 0x0,
(AttrNumber) 1, (AttrNumber) 1,
@ -690,7 +690,7 @@ func_get_candidates(char *funcname, int nargs)
index_endscan(sd); index_endscan(sd);
index_close(idesc); index_close(idesc);
heap_close(heapRelation); heap_close(heapRelation, AccessShareLock);
return candidates; return candidates;
} }
@ -1086,7 +1086,7 @@ find_inheritors(Oid relid, Oid **supervec)
visited = DLNewList(); visited = DLNewList();
inhrel = heap_openr(InheritsRelationName); inhrel = heap_openr(InheritsRelationName, AccessShareLock);
inhtupdesc = RelationGetDescr(inhrel); inhtupdesc = RelationGetDescr(inhrel);
/* /*
@ -1140,12 +1140,12 @@ find_inheritors(Oid relid, Oid **supervec)
if (qentry != (SuperQE *) NULL) if (qentry != (SuperQE *) NULL)
{ {
/* save the type id, rather than the relation id */ /* 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); elog(ERROR, "Relid %u does not exist", qentry->sqe_relid);
qentry->sqe_relid = typeTypeId(typenameType(RelationGetRelationName(rd)->data)); qentry->sqe_relid = typeTypeId(typenameType(RelationGetRelationName(rd)->data));
heap_close(rd); heap_close(rd, NoLock);
DLAddTail(visited, qe); DLAddTail(visited, qe);
@ -1153,7 +1153,7 @@ find_inheritors(Oid relid, Oid **supervec)
} }
} while (qentry != (SuperQE *) NULL); } while (qentry != (SuperQE *) NULL);
heap_close(inhrel); heap_close(inhrel, AccessShareLock);
if (nvisited > 0) if (nvisited > 0)
{ {
@ -1370,16 +1370,13 @@ ParseComplexProjection(ParseState *pstate,
*/ */
/* add a tlist to the func node and return the Iter */ /* 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)) if (RelationIsValid(rd))
{ {
relid = RelationGetRelid(rd); relid = RelationGetRelid(rd);
heap_close(rd);
}
if (RelationIsValid(rd))
{
func->func_tlist = setup_tlist(funcname, argrelid); func->func_tlist = setup_tlist(funcname, argrelid);
iter->itertype = attnumTypeId(rd, attnum); iter->itertype = attnumTypeId(rd, attnum);
heap_close(rd, NoLock);
return (Node *) iter; return (Node *) iter;
} }
else else
@ -1427,16 +1424,12 @@ ParseComplexProjection(ParseState *pstate,
{ {
/* add a tlist to the func node */ /* add a tlist to the func node */
rd = heap_openr(typeidTypeName(argtype)); rd = heap_openr(typeidTypeName(argtype), NoLock);
if (RelationIsValid(rd))
{
relid = RelationGetRelid(rd);
heap_close(rd);
}
if (RelationIsValid(rd)) if (RelationIsValid(rd))
{ {
Expr *newexpr; Expr *newexpr;
relid = RelationGetRelid(rd);
funcnode->func_tlist = setup_tlist(funcname, argrelid); funcnode->func_tlist = setup_tlist(funcname, argrelid);
funcnode->functype = attnumTypeId(rd, attnum); funcnode->functype = attnumTypeId(rd, attnum);
@ -1446,8 +1439,11 @@ ParseComplexProjection(ParseState *pstate,
newexpr->oper = (Node *) funcnode; newexpr->oper = (Node *) funcnode;
newexpr->args = expr->args; newexpr->args = expr->args;
heap_close(rd, NoLock);
return (Node *) newexpr; 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 * If the Param is a complex type, this could be a
* projection * projection
*/ */
rd = heap_openr(typeidTypeName(param->paramtype)); rd = heap_openr(typeidTypeName(param->paramtype), NoLock);
if (RelationIsValid(rd)) if (RelationIsValid(rd))
{ {
relid = RelationGetRelid(rd); relid = RelationGetRelid(rd);
heap_close(rd);
if ((attnum = get_attnum(relid, funcname)) if ((attnum = get_attnum(relid, funcname))
!= InvalidAttrNumber) != InvalidAttrNumber)
{ {
param->paramtype = attnumTypeId(rd, attnum); param->paramtype = attnumTypeId(rd, attnum);
param->param_tlist = setup_tlist(funcname, relid); param->param_tlist = setup_tlist(funcname, relid);
heap_close(rd, NoLock);
return (Node *) param; return (Node *) param;
} }
heap_close(rd, NoLock);
} }
break; break;
} }

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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; HeapScanDesc pg_operator_scan;
HeapTuple tup; HeapTuple tup;
Form_pg_operator oper; Form_pg_operator oper;
int nkeys;
int ncandidates = 0; int ncandidates = 0;
ScanKeyData opKey[3]; ScanKeyData opKey[3];
@ -91,13 +90,11 @@ binary_oper_get_candidates(char *opname,
F_CHAREQ, F_CHAREQ,
CharGetDatum('b')); CharGetDatum('b'));
nkeys = 2; pg_operator_desc = heap_openr(OperatorRelationName, AccessShareLock);
pg_operator_desc = heap_openr(OperatorRelationName);
pg_operator_scan = heap_beginscan(pg_operator_desc, pg_operator_scan = heap_beginscan(pg_operator_desc,
0, 0,
SnapshotSelf, /* ??? */ SnapshotSelf, /* ??? */
nkeys, 2,
opKey); opKey);
while (HeapTupleIsValid(tup = heap_getnext(pg_operator_scan, 0))) 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_endscan(pg_operator_scan);
heap_close(pg_operator_desc); heap_close(pg_operator_desc, AccessShareLock);
return ncandidates; return ncandidates;
} /* binary_oper_get_candidates() */ } /* binary_oper_get_candidates() */
@ -522,7 +519,7 @@ unary_oper_get_candidates(char *op,
fmgr_info(F_CHAREQ, (FmgrInfo *) &opKey[1].sk_func); fmgr_info(F_CHAREQ, (FmgrInfo *) &opKey[1].sk_func);
opKey[1].sk_argument = CharGetDatum(rightleft); 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, pg_operator_scan = heap_beginscan(pg_operator_desc,
0, 0,
SnapshotSelf, /* ??? */ SnapshotSelf, /* ??? */
@ -545,7 +542,7 @@ unary_oper_get_candidates(char *op,
} }
heap_endscan(pg_operator_scan); heap_endscan(pg_operator_scan);
heap_close(pg_operator_desc); heap_close(pg_operator_desc, AccessShareLock);
return ncandidates; return ncandidates;
} /* unary_oper_get_candidates() */ } /* unary_oper_get_candidates() */

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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->relname = pstrdup(relname);
rte->refname = pstrdup(refname); rte->refname = pstrdup(refname);
relation = heap_openr(relname); relation = heap_openr(relname, AccessShareLock);
if (relation == NULL)
elog(ERROR, "%s: %s",
relname, aclcheck_error_strings[ACLCHECK_NO_CLASS]);
rte->relid = RelationGetRelid(relation); rte->relid = RelationGetRelid(relation);
heap_close(relation, AccessShareLock);
heap_close(relation);
/* /*
* Flags - zero or more from inheritance,union,version or recursive * 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) if (rte == NULL)
rte = addRangeTableEntry(pstate, relname, refname, FALSE, FALSE); rte = addRangeTableEntry(pstate, relname, refname, FALSE, FALSE);
rel = heap_open(rte->relid); rel = heap_open(rte->relid, AccessShareLock);
if (rel == NULL)
elog(ERROR, "Unable to expand all -- heap_open failed on %s",
rte->refname);
maxattrs = RelationGetNumberOfAttributes(rel); maxattrs = RelationGetNumberOfAttributes(rel);
@ -278,7 +270,7 @@ expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
te_list = lappend(te_list, te); te_list = lappend(te_list, te);
} }
heap_close(rel); heap_close(rel, AccessShareLock);
return te_list; return te_list;
} }

View File

@ -6,7 +6,7 @@
* *
* *
* IDENTIFICATION * 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 * Get the usename of the rules event relation owner
*/ */
rte = (RangeTblEntry *) nth(rt_index - 1, parsetree->rtable); rte = (RangeTblEntry *) nth(rt_index - 1, parsetree->rtable);
ev_rel = heap_openr(rte->relname); ev_rel = heap_openr(rte->relname, AccessShareLock);
usertup = SearchSysCacheTuple(USESYSID, usertup = SearchSysCacheTuple(USESYSID,
ObjectIdGetDatum(ev_rel->rd_rel->relowner), ObjectIdGetDatum(ev_rel->rd_rel->relowner),
0, 0, 0); 0, 0, 0);
@ -193,7 +193,7 @@ checkLockPerms(List *locks, Query *parsetree, int rt_index)
elog(ERROR, "cache lookup for userid %d failed", elog(ERROR, "cache lookup for userid %d failed",
ev_rel->rd_rel->relowner); ev_rel->rd_rel->relowner);
} }
heap_close(ev_rel); heap_close(ev_rel, AccessShareLock);
evowner = nameout(&(((Form_pg_shadow) GETSTRUCT(usertup))->usename)); evowner = nameout(&(((Form_pg_shadow) GETSTRUCT(usertup))->usename));
/* /*

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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(); extern void eval_as_new_xact();
char *template; char *template;
eventrel = heap_openr(evobj); eventrel = heap_openr(evobj, AccessShareLock);
if (eventrel == NULL)
elog(ERROR, "rules cannot be defined on relations not in schema");
eventrel_oid = RelationGetRelid(eventrel); eventrel_oid = RelationGetRelid(eventrel);
/* /*
@ -90,7 +88,7 @@ InsertRule(char *rulname,
evslot_index = -1; evslot_index = -1;
else else
evslot_index = attnameAttNum(eventrel, (char *) evslot); evslot_index = attnameAttNum(eventrel, (char *) evslot);
heap_close(eventrel); heap_close(eventrel, AccessShareLock);
if (evinstead) if (evinstead)
is_instead = "t"; is_instead = "t";
@ -258,9 +256,7 @@ DefineQueryRewrite(RuleStmt *stmt)
* ... the targetlist of the SELECT action must exactly match the * ... the targetlist of the SELECT action must exactly match the
* event relation, ... * event relation, ...
*/ */
event_relation = heap_openr(event_obj->relname); event_relation = heap_openr(event_obj->relname, AccessShareLock);
if (event_relation == NULL)
elog(ERROR, "virtual relations not supported yet");
if (event_relation->rd_att->natts != length(query->targetList)) if (event_relation->rd_att->natts != length(query->targetList))
elog(ERROR, "select rules target list must match event relations structure"); 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 * LIMIT in view is not supported
@ -332,9 +328,7 @@ DefineQueryRewrite(RuleStmt *stmt)
* This rule is allowed - install it. * This rule is allowed - install it.
*/ */
event_relation = heap_openr(event_obj->relname); event_relation = heap_openr(event_obj->relname, AccessShareLock);
if (event_relation == NULL)
elog(ERROR, "virtual relations not supported yet");
ev_relid = RelationGetRelid(event_relation); ev_relid = RelationGetRelid(event_relation);
if (eslot_string == NULL) if (eslot_string == NULL)
@ -347,7 +341,7 @@ DefineQueryRewrite(RuleStmt *stmt)
event_attno = attnameAttNum(event_relation, eslot_string); event_attno = attnameAttNum(event_relation, eslot_string);
event_attype = attnumTypeId(event_relation, event_attno); event_attype = attnumTypeId(event_relation, event_attno);
} }
heap_close(event_relation); heap_close(event_relation, AccessShareLock);
/* fix bug about instead nothing */ /* fix bug about instead nothing */
ValidateRule(event_type, event_obj->relname, ValidateRule(event_type, event_obj->relname,

View File

@ -6,7 +6,7 @@
* *
* *
* IDENTIFICATION * 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; continue;
} }
rel = heap_openr(rte->relname); rel = heap_openr(rte->relname, AccessShareLock);
if (rel->rd_rules == NULL) if (rel->rd_rules == NULL)
{ {
heap_close(rel); heap_close(rel, AccessShareLock);
continue; continue;
} }
@ -2112,7 +2112,7 @@ fireRIRrules(Query *parsetree)
&modified); &modified);
} }
heap_close(rel); heap_close(rel, AccessShareLock);
} }
fireRIRonSubselect((Node *) parsetree); 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. * the statement is an update, insert or delete - fire rules on it.
*/ */
rt_entry = rt_fetch(result_relation, parsetree->rtable); 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; rt_entry_locks = rt_entry_relation->rd_rules;
heap_close(rt_entry_relation); heap_close(rt_entry_relation, AccessShareLock);
if (rt_entry_locks != NULL) if (rt_entry_locks != NULL)
{ {
@ -2469,7 +2469,6 @@ RewriteQuery(Query *parsetree, bool *instead_flag, List **qual_products)
} }
return product_queries; return product_queries;
} }
@ -2585,7 +2584,7 @@ RewritePreprocessQuery(Query *parsetree)
rte = (RangeTblEntry *) nth(parsetree->resultRelation - 1, rte = (RangeTblEntry *) nth(parsetree->resultRelation - 1,
parsetree->rtable); parsetree->rtable);
rd = heap_openr(rte->relname); rd = heap_openr(rte->relname, AccessShareLock);
foreach(tl, parsetree->targetList) foreach(tl, parsetree->targetList)
{ {
@ -2597,7 +2596,7 @@ RewritePreprocessQuery(Query *parsetree)
tle->resdom->resno = 0; tle->resdom->resno = 0;
} }
heap_close(rd); heap_close(rd, AccessShareLock);
} }
} }

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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. * Open the pg_rewrite relation.
*/ */
RewriteRelation = heap_openr(RewriteRelationName); RewriteRelation = heap_openr(RewriteRelationName, RowExclusiveLock);
/* /*
* Scan the RuleRelation ('pg_rewrite') until we find a tuple * Scan the RuleRelation ('pg_rewrite') until we find a tuple
@ -90,7 +90,7 @@ RemoveRewriteRule(char *ruleName)
*/ */
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
{ {
heap_close(RewriteRelation); heap_close(RewriteRelation, RowExclusiveLock);
elog(ERROR, "Rule '%s' not found\n", ruleName); elog(ERROR, "Rule '%s' not found\n", ruleName);
} }
@ -125,7 +125,7 @@ RemoveRewriteRule(char *ruleName)
heap_delete(RewriteRelation, &tuple->t_self, NULL); heap_delete(RewriteRelation, &tuple->t_self, NULL);
pfree(tuple); pfree(tuple);
heap_close(RewriteRelation); heap_close(RewriteRelation, RowExclusiveLock);
} }
/* /*
@ -144,7 +144,7 @@ RelationRemoveRules(Oid relid)
/* /*
* Open the pg_rewrite relation. * 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 * 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_delete(RewriteRelation, &tuple->t_self, NULL);
heap_endscan(scanDesc); heap_endscan(scanDesc);
heap_close(RewriteRelation); heap_close(RewriteRelation, RowExclusiveLock);
} }

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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; char *rule_evqual_string = NULL;
Node *rule_evqual = NULL; Node *rule_evqual = NULL;
ruleRelation = heap_openr(RewriteRelationName); ruleRelation = heap_openr(RewriteRelationName, AccessShareLock);
ruleTupdesc = RelationGetDescr(ruleRelation); ruleTupdesc = RelationGetDescr(ruleRelation);
ruletuple = SearchSysCacheTuple(RULOID, ruletuple = SearchSysCacheTuple(RULOID,
ObjectIdGetDatum(ruleoid), ObjectIdGetDatum(ruleoid),
@ -68,7 +68,7 @@ RuleIdGetActionInfo(Oid ruleoid, bool *instead_flag, Query **parseTrees)
ruleparse = (Query *) stringToNode(ruleaction); ruleparse = (Query *) stringToNode(ruleaction);
rule_evqual = (Node *) stringToNode(rule_evqual_string); rule_evqual = (Node *) stringToNode(rule_evqual_string);
heap_close(ruleRelation); heap_close(ruleRelation, AccessShareLock);
*parseTrees = ruleparse; *parseTrees = ruleparse;
return rule_evqual; return rule_evqual;
@ -79,23 +79,11 @@ RuleIdGetActionInfo(Oid ruleoid, bool *instead_flag, Query **parseTrees)
int int
IsDefinedRewriteRule(char *ruleName) IsDefinedRewriteRule(char *ruleName)
{ {
Relation RewriteRelation = NULL;
HeapTuple tuple; HeapTuple tuple;
/*
* Open the pg_rewrite relation.
*/
RewriteRelation = heap_openr(RewriteRelationName);
tuple = SearchSysCacheTuple(REWRITENAME, tuple = SearchSysCacheTuple(REWRITENAME,
PointerGetDatum(ruleName), PointerGetDatum(ruleName),
0, 0, 0); 0, 0, 0);
/*
* return whether or not the rewrite rule existed
*/
heap_close(RewriteRelation);
return HeapTupleIsValid(tuple); return HeapTupleIsValid(tuple);
} }
@ -111,12 +99,12 @@ setRelhasrulesInRelation(Oid relationId, bool relhasrules)
* pg_relation), find the appropriate tuple, and add the specified * pg_relation), find the appropriate tuple, and add the specified
* lock to it. * lock to it.
*/ */
relationRelation = heap_openr(RelationRelationName, RowExclusiveLock);
tuple = SearchSysCacheTupleCopy(RELOID, tuple = SearchSysCacheTupleCopy(RELOID,
ObjectIdGetDatum(relationId), ObjectIdGetDatum(relationId),
0, 0, 0); 0, 0, 0);
Assert(HeapTupleIsValid(tuple)); Assert(HeapTupleIsValid(tuple));
relationRelation = heap_openr(RelationRelationName);
((Form_pg_class) GETSTRUCT(tuple))->relhasrules = relhasrules; ((Form_pg_class) GETSTRUCT(tuple))->relhasrules = relhasrules;
heap_replace(relationRelation, &tuple->t_self, tuple, NULL); heap_replace(relationRelation, &tuple->t_self, tuple, NULL);
@ -126,7 +114,7 @@ setRelhasrulesInRelation(Oid relationId, bool relhasrules)
CatalogCloseIndices(Num_pg_class_indices, idescs); CatalogCloseIndices(Num_pg_class_indices, idescs);
pfree(tuple); pfree(tuple);
heap_close(relationRelation); heap_close(relationRelation, RowExclusiveLock);
} }
void void
@ -162,7 +150,7 @@ prs2_addToRelation(Oid relid,
thisRule->actions = actions; thisRule->actions = actions;
thisRule->isInstead = isInstead; thisRule->isInstead = isInstead;
relation = heap_open(relid); relation = heap_open(relid, AccessShareLock);
/* /*
* modify or create a RuleLock cached by Relation * modify or create a RuleLock cached by Relation
@ -200,9 +188,7 @@ prs2_addToRelation(Oid relid,
rulelock->numLocks++; rulelock->numLocks++;
} }
heap_close(relation); heap_close(relation, AccessShareLock);
return;
} }
void void
@ -214,7 +200,7 @@ prs2_deleteFromRelation(Oid relid, Oid ruleId)
int i; int i;
MemoryContext oldcxt; MemoryContext oldcxt;
relation = heap_open(relid); relation = heap_open(relid, AccessShareLock);
rulelock = relation->rd_rules; rulelock = relation->rd_rules;
Assert(rulelock != NULL); Assert(rulelock != NULL);
@ -245,5 +231,5 @@ prs2_deleteFromRelation(Oid relid, Oid ruleId)
rulelock->numLocks--; rulelock->numLocks--;
} }
heap_close(relation); heap_close(relation, AccessShareLock);
} }

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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)) if (!BufferIsLocal(buffer))
{ {
LockRelId *lrelId = &(((LockInfo) (relation->lockInfo))->lockRelId); LockRelId *lrelId = & relation->rd_lockInfo.lockRelId;
bufHdr = &BufferDescriptors[buffer - 1]; bufHdr = &BufferDescriptors[buffer - 1];
SpinAcquire(BufMgrLock); SpinAcquire(BufMgrLock);
@ -813,6 +813,7 @@ FlushBuffer(Buffer buffer, bool release)
status = smgrflush(DEFAULT_SMGR, bufrel, bufHdr->tag.blockNum, status = smgrflush(DEFAULT_SMGR, bufrel, bufHdr->tag.blockNum,
(char *) MAKE_PTR(bufHdr->data)); (char *) MAKE_PTR(bufHdr->data));
/* drop relcache refcount incremented by RelationIdCacheGetRelation */
RelationDecrementReferenceCount(bufrel); RelationDecrementReferenceCount(bufrel);
if (status == SM_FAIL) if (status == SM_FAIL)
@ -993,6 +994,7 @@ BufferSync()
elog(ERROR, "BufferSync: write error %u for %s", elog(ERROR, "BufferSync: write error %u for %s",
bufHdr->tag.blockNum, bufHdr->sb_relname); bufHdr->tag.blockNum, bufHdr->sb_relname);
} }
/* drop refcount from RelationIdCacheGetRelation */
if (reln != (Relation) NULL) if (reln != (Relation) NULL)
RelationDecrementReferenceCount(reln); RelationDecrementReferenceCount(reln);
continue; continue;
@ -1047,6 +1049,7 @@ BufferSync()
*/ */
if (!(bufHdr->flags & BM_JUST_DIRTIED)) if (!(bufHdr->flags & BM_JUST_DIRTIED))
bufHdr->flags &= ~BM_DIRTY; bufHdr->flags &= ~BM_DIRTY;
/* drop refcount from RelationIdCacheGetRelation */
if (reln != (Relation) NULL) if (reln != (Relation) NULL)
RelationDecrementReferenceCount(reln); RelationDecrementReferenceCount(reln);
} }
@ -1282,14 +1285,16 @@ BufferGetRelation(Buffer buffer)
/* XXX should be a critical section */ /* XXX should be a critical section */
relid = BufferDescriptors[buffer - 1].tag.relId.relId; relid = BufferDescriptors[buffer - 1].tag.relId.relId;
relation = RelationIdGetRelation(relid); relation = RelationIdGetRelation(relid);
Assert(relation);
/* drop relcache refcount incremented by RelationIdGetRelation */
RelationDecrementReferenceCount(relation); RelationDecrementReferenceCount(relation);
if (RelationHasReferenceCountZero(relation)) if (RelationHasReferenceCountZero(relation))
{ {
/* /*
* elog(NOTICE, "BufferGetRelation: 0->1"); * XXX why??
*/ */
RelationIncrementReferenceCount(relation); RelationIncrementReferenceCount(relation);
@ -1342,7 +1347,6 @@ BufferReplace(BufferDesc *bufHdr, bool bufferLockHeld)
} }
else else
{ {
/* blind write always flushes */ /* blind write always flushes */
status = smgrblindwrt(DEFAULT_SMGR, bufHdr->sb_dbname, status = smgrblindwrt(DEFAULT_SMGR, bufHdr->sb_dbname,
bufHdr->sb_relname, bufdb, bufrel, bufHdr->sb_relname, bufdb, bufrel,
@ -1350,6 +1354,7 @@ BufferReplace(BufferDesc *bufHdr, bool bufferLockHeld)
(char *) MAKE_PTR(bufHdr->data)); (char *) MAKE_PTR(bufHdr->data));
} }
/* drop relcache refcount incremented by RelationIdCacheGetRelation */
if (reln != (Relation) NULL) if (reln != (Relation) NULL)
RelationDecrementReferenceCount(reln); RelationDecrementReferenceCount(reln);

View File

@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * 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, smgrwrite(DEFAULT_SMGR, bufrel, bufHdr->tag.blockNum,
(char *) MAKE_PTR(bufHdr->data)); (char *) MAKE_PTR(bufHdr->data));
LocalBufferFlushCount++; LocalBufferFlushCount++;
/* drop relcache refcount incremented by RelationIdCacheGetRelation */
RelationDecrementReferenceCount(bufrel); RelationDecrementReferenceCount(bufrel);
} }
@ -187,6 +189,8 @@ FlushLocalBuffer(Buffer buffer, bool release)
smgrflush(DEFAULT_SMGR, bufrel, bufHdr->tag.blockNum, smgrflush(DEFAULT_SMGR, bufrel, bufHdr->tag.blockNum,
(char *) MAKE_PTR(bufHdr->data)); (char *) MAKE_PTR(bufHdr->data));
LocalBufferFlushCount++; LocalBufferFlushCount++;
/* drop relcache refcount incremented by RelationIdCacheGetRelation */
RelationDecrementReferenceCount(bufrel); RelationDecrementReferenceCount(bufrel);
Assert(LocalRefCount[bufid] > 0); Assert(LocalRefCount[bufid] > 0);
@ -260,6 +264,8 @@ LocalBufferSync(void)
smgrwrite(DEFAULT_SMGR, bufrel, buf->tag.blockNum, smgrwrite(DEFAULT_SMGR, bufrel, buf->tag.blockNum,
(char *) MAKE_PTR(buf->data)); (char *) MAKE_PTR(buf->data));
LocalBufferFlushCount++; LocalBufferFlushCount++;
/* drop relcache refcount from RelationIdCacheGetRelation */
RelationDecrementReferenceCount(bufrel); RelationDecrementReferenceCount(bufrel);
buf->tag.relId.relId = InvalidOid; buf->tag.relId.relId = InvalidOid;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 */ /* make the relation visible in this transaction */
CommandCounterIncrement(); CommandCounterIncrement();
r = heap_openr(objname);
if (!RelationIsValid(r)) /*--------------------
{ * We hold AccessShareLock on any large object we have open
elog(ERROR, "cannot create large object on %s under inversion", * by inv_create or inv_open; it is released by inv_close.
smgrout(DEFAULT_SMGR)); * 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 * Now create a btree index on the relation's olastbyte attribute to
@ -205,10 +208,7 @@ inv_open(Oid lobjId, int flags)
char *indname; char *indname;
Relation indrel; Relation indrel;
r = heap_open(lobjId); r = heap_open(lobjId, AccessShareLock);
if (!RelationIsValid(r))
return (LargeObjectDesc *) NULL;
indname = pstrdup((r->rd_rel->relname).data); indname = pstrdup((r->rd_rel->relname).data);
@ -262,8 +262,8 @@ inv_close(LargeObjectDesc *obj_desc)
obj_desc->iscan = NULL; obj_desc->iscan = NULL;
} }
heap_close(obj_desc->heap_r);
index_close(obj_desc->index_r); index_close(obj_desc->index_r);
heap_close(obj_desc->heap_r, AccessShareLock);
pfree(obj_desc); pfree(obj_desc);
} }
@ -279,7 +279,7 @@ inv_destroy(Oid lobjId)
Relation r; Relation r;
r = (Relation) RelationIdGetRelation(lobjId); r = (Relation) RelationIdGetRelation(lobjId);
if (!RelationIsValid(r) || r->rd_rel->relkind == RELKIND_INDEX) if (!RelationIsValid(r) || r->rd_rel->relkind != RELKIND_LOBJECT)
return -1; return -1;
heap_destroy_with_catalog(r->rd_rel->relname.data); 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)) 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); obj_desc->flags |= (IFS_WRLOCK | IFS_RDLOCK);
} }

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 "postgres.h"
#include "access/transam.h" #include "access/transam.h"
#include "catalog/catalog.h" #include "catalog/catalog.h"
#include "miscadmin.h"
#include "utils/inval.h" #include "utils/inval.h"
extern Oid MyDatabaseId;
static LOCKMASK LockConflicts[] = { static LOCKMASK LockConflicts[] = {
(int) NULL, (int) NULL,
@ -106,37 +107,25 @@ InitLockTable()
/* /*
* RelationInitLockInfo * RelationInitLockInfo
* Initializes the lock information in a relation descriptor. * Initializes the lock information in a relation descriptor.
*
* relcache.c must call this during creation of any reldesc.
*/ */
void void
RelationInitLockInfo(Relation relation) RelationInitLockInfo(Relation relation)
{ {
LockInfo info;
char *relname; char *relname;
MemoryContext oldcxt;
extern Oid MyDatabaseId; /* XXX use include */
extern GlobalMemory CacheCxt;
Assert(RelationIsValid(relation)); Assert(RelationIsValid(relation));
Assert(OidIsValid(RelationGetRelid(relation))); Assert(OidIsValid(RelationGetRelid(relation)));
info = (LockInfo) relation->lockInfo;
if (LockInfoIsValid(info))
return;
relname = (char *) RelationGetRelationName(relation); relname = (char *) RelationGetRelationName(relation);
oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); relation->rd_lockInfo.lockRelId.relId = RelationGetRelid(relation);
info = (LockInfo) palloc(sizeof(LockInfoData));
MemoryContextSwitchTo(oldcxt);
info->lockRelId.relId = RelationGetRelid(relation);
if (IsSharedSystemRelationName(relname)) if (IsSharedSystemRelationName(relname))
info->lockRelId.dbId = InvalidOid; relation->rd_lockInfo.lockRelId.dbId = InvalidOid;
else else
info->lockRelId.dbId = MyDatabaseId; relation->rd_lockInfo.lockRelId.dbId = MyDatabaseId;
relation->lockInfo = (Pointer) info;
} }
/* /*
@ -145,20 +134,14 @@ RelationInitLockInfo(Relation relation)
void void
LockRelation(Relation relation, LOCKMODE lockmode) LockRelation(Relation relation, LOCKMODE lockmode)
{ {
LockInfo lockinfo;
LOCKTAG tag; LOCKTAG tag;
if (LockingDisabled()) if (LockingDisabled())
return; return;
if (!LockInfoIsValid(relation->lockInfo))
RelationInitLockInfo(relation);
lockinfo = (LockInfo) relation->lockInfo;
MemSet(&tag, 0, sizeof(tag)); MemSet(&tag, 0, sizeof(tag));
tag.relId = lockinfo->lockRelId.relId; tag.relId = relation->rd_lockInfo.lockRelId.relId;
tag.dbId = lockinfo->lockRelId.dbId; tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
tag.objId.blkno = InvalidBlockNumber; tag.objId.blkno = InvalidBlockNumber;
LockAcquire(LockTableId, &tag, lockmode); LockAcquire(LockTableId, &tag, lockmode);
@ -180,28 +163,17 @@ LockRelation(Relation relation, LOCKMODE lockmode)
void void
UnlockRelation(Relation relation, LOCKMODE lockmode) UnlockRelation(Relation relation, LOCKMODE lockmode)
{ {
LockInfo lockinfo;
LOCKTAG tag; LOCKTAG tag;
if (LockingDisabled()) if (LockingDisabled())
return; 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)); MemSet(&tag, 0, sizeof(tag));
tag.relId = lockinfo->lockRelId.relId; tag.relId = relation->rd_lockInfo.lockRelId.relId;
tag.dbId = lockinfo->lockRelId.dbId; tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
tag.objId.blkno = InvalidBlockNumber; tag.objId.blkno = InvalidBlockNumber;
LockRelease(LockTableId, &tag, lockmode); LockRelease(LockTableId, &tag, lockmode);
return;
} }
/* /*
@ -210,24 +182,17 @@ UnlockRelation(Relation relation, LOCKMODE lockmode)
void void
LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode) LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
{ {
LockInfo lockinfo;
LOCKTAG tag; LOCKTAG tag;
if (LockingDisabled()) if (LockingDisabled())
return; return;
if (!LockInfoIsValid(relation->lockInfo))
RelationInitLockInfo(relation);
lockinfo = (LockInfo) relation->lockInfo;
MemSet(&tag, 0, sizeof(tag)); MemSet(&tag, 0, sizeof(tag));
tag.relId = lockinfo->lockRelId.relId; tag.relId = relation->rd_lockInfo.lockRelId.relId;
tag.dbId = lockinfo->lockRelId.dbId; tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
tag.objId.blkno = blkno; tag.objId.blkno = blkno;
LockAcquire(LockTableId, &tag, lockmode); LockAcquire(LockTableId, &tag, lockmode);
return;
} }
/* /*
@ -236,28 +201,17 @@ LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
void void
UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode) UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
{ {
LockInfo lockinfo;
LOCKTAG tag; LOCKTAG tag;
if (LockingDisabled()) if (LockingDisabled())
return; 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)); MemSet(&tag, 0, sizeof(tag));
tag.relId = lockinfo->lockRelId.relId; tag.relId = relation->rd_lockInfo.lockRelId.relId;
tag.dbId = lockinfo->lockRelId.dbId; tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
tag.objId.blkno = blkno; tag.objId.blkno = blkno;
LockRelease(LockTableId, &tag, lockmode); LockRelease(LockTableId, &tag, lockmode);
return;
} }
void void
@ -274,7 +228,6 @@ XactLockTableInsert(TransactionId xid)
tag.objId.xid = xid; tag.objId.xid = xid;
LockAcquire(LockTableId, &tag, ExclusiveLock); LockAcquire(LockTableId, &tag, ExclusiveLock);
return;
} }
void void
@ -291,7 +244,6 @@ XactLockTableDelete(TransactionId xid)
tag.objId.xid = xid; tag.objId.xid = xid;
LockRelease(LockTableId, &tag, ExclusiveLock); LockRelease(LockTableId, &tag, ExclusiveLock);
return;
} }
void void
@ -316,6 +268,4 @@ XactLockTableWait(TransactionId xid)
*/ */
if (!TransactionIdDidCommit(xid) && !TransactionIdDidAbort(xid)) if (!TransactionIdDidCommit(xid) && !TransactionIdDidAbort(xid))
TransactionIdAbort(xid); TransactionIdAbort(xid);
return;
} }

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* Outside modules can create a lock table and acquire/release * Outside modules can create a lock table and acquire/release
@ -596,7 +596,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
if (!result) if (!result)
{ {
elog(NOTICE, "LockAcquire: xid table corrupted"); 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"); TPRINTF(TRACE_USERLOCKS, "LockRelease: no lock with this tag");
else else
#endif #endif
elog(NOTICE, "LockReplace: xid table corrupted"); elog(NOTICE, "LockRelease: xid table corrupted");
return FALSE; return FALSE;
} }
XID_PRINT("LockRelease: found", result); XID_PRINT("LockRelease: found", result);

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * 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: case T_DestroyStmt:
{ {
DestroyStmt *stmt = (DestroyStmt *) parsetree; DestroyStmt *stmt = (DestroyStmt *) parsetree;
List *arg;
List *args = stmt->relNames; List *args = stmt->relNames;
Relation rel; List *arg;
PS_SET_STATUS(commandTag = "DROP"); PS_SET_STATUS(commandTag = "DROP");
CHECK_IF_ABORTED(); CHECK_IF_ABORTED();
/* check as much as we can before we start dropping ... */
foreach(arg, args) foreach(arg, args)
{ {
Relation rel;
relname = strVal(lfirst(arg)); relname = strVal(lfirst(arg));
if (!allowSystemTableMods && IsSystemRelationName(relname)) if (!allowSystemTableMods && IsSystemRelationName(relname))
elog(ERROR, "class \"%s\" is a system catalog", elog(ERROR, "class \"%s\" is a system catalog",
relname); relname);
rel = heap_openr(relname); rel = heap_openr(relname, AccessExclusiveLock);
if (RelationIsValid(rel)) if (stmt->sequence &&
{ rel->rd_rel->relkind != RELKIND_SEQUENCE)
if (stmt->sequence && elog(ERROR, "Use DROP TABLE to drop table '%s'",
rel->rd_rel->relkind != RELKIND_SEQUENCE) relname);
elog(ERROR, "Use DROP TABLE to drop table '%s'", if (!(stmt->sequence) &&
relname); rel->rd_rel->relkind == RELKIND_SEQUENCE)
if (!(stmt->sequence) && elog(ERROR, "Use DROP SEQUENCE to drop sequence '%s'",
rel->rd_rel->relkind == RELKIND_SEQUENCE) relname);
elog(ERROR, "Use DROP SEQUENCE to drop sequence '%s'", /* close rel, but keep lock until end of xact */
relname); heap_close(rel, NoLock);
heap_close(rel);
}
#ifndef NO_SECURITY #ifndef NO_SECURITY
if (!pg_ownercheck(userName, relname, RELNAME)) if (!pg_ownercheck(userName, relname, RELNAME))
elog(ERROR, "you do not own class \"%s\"", elog(ERROR, "you do not own class \"%s\"",
relname); relname);
#endif #endif
} }
/* OK, terminate 'em all */
foreach(arg, args) foreach(arg, args)
{ {
relname = strVal(lfirst(arg)); relname = strVal(lfirst(arg));

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 */ /* Open the relation and get a relation descriptor */
relation_to_scan = heap_openr(relation); relation_to_scan = heap_openr(relation, AccessShareLock);
if (!RelationIsValid(relation_to_scan))
{
elog(ERROR, "int4notin: unknown relation %s",
relation);
}
/* Find the column to search */ /* Find the column to search */
@ -95,7 +90,9 @@ int4notin(int32 not_in_arg, char *relation_and_attr)
} }
/* close the relation */ /* close the relation */
heap_close(relation_to_scan); heap_endscan(scan_descriptor);
heap_close(relation_to_scan, AccessShareLock);
return retval; return retval;
} }

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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, (RegProcedure) F_NAMEEQ,
PointerGetDatum(pro_name_or_oid)); PointerGetDatum(pro_name_or_oid));
hdesc = heap_openr(ProcedureRelationName); hdesc = heap_openr(ProcedureRelationName, AccessShareLock);
idesc = index_openr(ProcedureNameIndex); idesc = index_openr(ProcedureNameIndex);
sd = index_beginscan(idesc, false, 1, skey); sd = index_beginscan(idesc, false, 1, skey);
@ -102,6 +102,7 @@ regprocin(char *pro_name_or_oid)
index_endscan(sd); index_endscan(sd);
pfree(sd); pfree(sd);
index_close(idesc); index_close(idesc);
heap_close(hdesc, AccessShareLock);
if (matches > 1) 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); 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; ScanKeyData key;
bool isnull; bool isnull;
proc = heap_openr(ProcedureRelationName); proc = heap_openr(ProcedureRelationName, AccessShareLock);
if (!RelationIsValid(proc))
{
elog(ERROR, "regprocin: could not open %s",
ProcedureRelationName);
return 0;
}
ScanKeyEntryInitialize(&key, ScanKeyEntryInitialize(&key,
(bits16) 0, (bits16) 0,
(AttrNumber) 1, (AttrNumber) 1,
@ -132,8 +127,8 @@ regprocin(char *pro_name_or_oid)
procscan = heap_beginscan(proc, 0, SnapshotNow, 1, &key); procscan = heap_beginscan(proc, 0, SnapshotNow, 1, &key);
if (!HeapScanIsValid(procscan)) if (!HeapScanIsValid(procscan))
{ {
heap_close(proc); heap_close(proc, AccessShareLock);
elog(ERROR, "regprocin: could not being scan of %s", elog(ERROR, "regprocin: could not begin scan of %s",
ProcedureRelationName); ProcedureRelationName);
return 0; return 0;
} }
@ -151,7 +146,7 @@ regprocin(char *pro_name_or_oid)
result = (RegProcedure) 0; result = (RegProcedure) 0;
heap_endscan(procscan); heap_endscan(procscan);
heap_close(proc); heap_close(proc, AccessShareLock);
} }
return (int32) result; return (int32) result;
@ -193,12 +188,7 @@ regprocout(RegProcedure proid)
HeapScanDesc procscan; HeapScanDesc procscan;
ScanKeyData key; ScanKeyData key;
proc = heap_openr(ProcedureRelationName); proc = heap_openr(ProcedureRelationName, AccessShareLock);
if (!RelationIsValid(proc))
{
elog(ERROR, "regprocout: could not open %s", ProcedureRelationName);
return 0;
}
ScanKeyEntryInitialize(&key, ScanKeyEntryInitialize(&key,
(bits16) 0, (bits16) 0,
(AttrNumber) ObjectIdAttributeNumber, (AttrNumber) ObjectIdAttributeNumber,
@ -208,8 +198,8 @@ regprocout(RegProcedure proid)
procscan = heap_beginscan(proc, 0, SnapshotNow, 1, &key); procscan = heap_beginscan(proc, 0, SnapshotNow, 1, &key);
if (!HeapScanIsValid(procscan)) if (!HeapScanIsValid(procscan))
{ {
heap_close(proc); heap_close(proc, AccessShareLock);
elog(ERROR, "regprocout: could not being scan of %s", elog(ERROR, "regprocout: could not begin scan of %s",
ProcedureRelationName); ProcedureRelationName);
return 0; return 0;
} }
@ -232,8 +222,7 @@ regprocout(RegProcedure proid)
result[1] = '\0'; result[1] = '\0';
} }
heap_endscan(procscan); heap_endscan(procscan);
heap_close(proc); heap_close(proc, AccessShareLock);
return result;
} }
return result; return result;

View File

@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * 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; HeapTuple typeTuple;
FmgrInfo inputproc; FmgrInfo inputproc;
rel = heap_openr(StatisticRelationName); rel = heap_openr(StatisticRelationName, AccessShareLock);
key[0].sk_argument = ObjectIdGetDatum(relid); key[0].sk_argument = ObjectIdGetDatum(relid);
key[1].sk_argument = Int16GetDatum((int16) attnum); key[1].sk_argument = Int16GetDatum((int16) attnum);
@ -609,7 +609,7 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid typid, int32 typmod,
{ {
/* no such stats entry */ /* no such stats entry */
heap_endscan(scan); heap_endscan(scan);
heap_close(rel); heap_close(rel, AccessShareLock);
return false; return false;
} }
@ -694,7 +694,7 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid typid, int32 typmod,
} }
heap_endscan(scan); heap_endscan(scan);
heap_close(rel); heap_close(rel, AccessShareLock);
return true; return true;
} }

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * 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] = ' '; replNull[i] = ' ';
/* change the pg_proc tuple */ /* change the pg_proc tuple */
procrel = heap_openr(ProcedureRelationName); procrel = heap_openr(ProcedureRelationName, RowExclusiveLock);
LockRelation(procrel, AccessExclusiveLock);
tup = SearchSysCacheTuple(PROOID, tup = SearchSysCacheTuple(PROOID,
ObjectIdGetDatum(setoid), ObjectIdGetDatum(setoid),
@ -131,8 +130,7 @@ SetDefine(char *querystr, char *typename)
CatalogIndexInsert(idescs, Num_pg_proc_indices, procrel, newtup); CatalogIndexInsert(idescs, Num_pg_proc_indices, procrel, newtup);
CatalogCloseIndices(Num_pg_proc_indices, idescs); CatalogCloseIndices(Num_pg_proc_indices, idescs);
} }
UnlockRelation(procrel, AccessExclusiveLock); heap_close(procrel, RowExclusiveLock);
heap_close(procrel);
} }
return setoid; return setoid;
} }

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 * If no relation was passed we must open it to get access to
* its fields. If one of the other caches has already opened * 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)) if (!RelationIsValid(relation))
@ -155,9 +156,9 @@ CatalogCacheInitializeCache(struct catcache * cache,
* ---------------- * ----------------
*/ */
if (cp) if (cp)
relation = heap_open(cp->relationId); relation = heap_open(cp->relationId, NoLock);
else else
relation = heap_openr(cache->cc_relname); relation = heap_openr(cache->cc_relname, NoLock);
didopen = 1; didopen = 1;
} }
@ -217,7 +218,7 @@ CatalogCacheInitializeCache(struct catcache * cache,
* ---------------- * ----------------
*/ */
if (didopen) if (didopen)
heap_close(relation); heap_close(relation, NoLock);
/* ---------------- /* ----------------
* initialize index information for the cache. this * initialize index information for the cache. this
@ -891,10 +892,10 @@ SearchSysCache(struct catcache * cache,
DLMoveToFront(elt); DLMoveToFront(elt);
#ifdef CACHEDEBUG #ifdef CACHEDEBUG
relation = heap_open(cache->relationId); relation = heap_open(cache->relationId, NoLock);
CACHE3_elog(DEBUG, "SearchSysCache(%s): found in bucket %d", CACHE3_elog(DEBUG, "SearchSysCache(%s): found in bucket %d",
RelationGetRelationName(relation), hash); RelationGetRelationName(relation), hash);
heap_close(relation); heap_close(relation, NoLock);
#endif /* CACHEDEBUG */ #endif /* CACHEDEBUG */
return ct->ct_tup; return ct->ct_tup;
@ -925,7 +926,7 @@ SearchSysCache(struct catcache * cache,
* open the relation associated with the cache * open the relation associated with the cache
* ---------------- * ----------------
*/ */
relation = heap_open(cache->relationId); relation = heap_open(cache->relationId, AccessShareLock);
CACHE2_elog(DEBUG, "SearchSysCache(%s)", CACHE2_elog(DEBUG, "SearchSysCache(%s)",
RelationGetRelationName(relation)); RelationGetRelationName(relation));
@ -1082,7 +1083,7 @@ SearchSysCache(struct catcache * cache,
* and return the tuple we found (or NULL) * and return the tuple we found (or NULL)
* ---------------- * ----------------
*/ */
heap_close(relation); heap_close(relation, AccessShareLock);
MemoryContextSwitchTo(oldcxt); MemoryContextSwitchTo(oldcxt);
return ntp; return ntp;
@ -1146,8 +1147,6 @@ RelationInvalidateCatalogCacheTuple(Relation relation,
(*function) (ccp->id, (*function) (ccp->id,
CatalogCacheComputeTupleHashIndex(ccp, relation, tuple), CatalogCacheComputeTupleHashIndex(ccp, relation, tuple),
&tuple->t_self); &tuple->t_self);
heap_close(relation);
} }
/* ---------------- /* ----------------

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 * 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_scan = heap_beginscan(pg_class_desc, 0, SnapshotNow, 1, &key);
pg_class_tuple = heap_getnext(pg_class_scan, 0); pg_class_tuple = heap_getnext(pg_class_scan, 0);
@ -361,7 +361,7 @@ scan_pg_rel_seq(RelationBuildDescInfo buildinfo)
/* all done */ /* all done */
heap_endscan(pg_class_scan); heap_endscan(pg_class_scan);
heap_close(pg_class_desc); heap_close(pg_class_desc, AccessShareLock);
return return_tuple; return return_tuple;
} }
@ -372,9 +372,7 @@ scan_pg_rel_ind(RelationBuildDescInfo buildinfo)
Relation pg_class_desc; Relation pg_class_desc;
HeapTuple return_tuple; HeapTuple return_tuple;
pg_class_desc = heap_openr(RelationRelationName); pg_class_desc = heap_openr(RelationRelationName, AccessShareLock);
if (!IsInitProcessingMode())
LockRelation(pg_class_desc, AccessShareLock);
switch (buildinfo.infotype) switch (buildinfo.infotype)
{ {
@ -389,18 +387,10 @@ scan_pg_rel_ind(RelationBuildDescInfo buildinfo)
default: default:
elog(ERROR, "ScanPgRelation: bad buildinfo"); elog(ERROR, "ScanPgRelation: bad buildinfo");
return_tuple = NULL; /* keep compiler quiet */
/*
* XXX I hope this is right. It seems better than returning
* an uninitialized value
*/
return_tuple = NULL;
} }
/* all done */ heap_close(pg_class_desc, AccessShareLock);
if (!IsInitProcessingMode())
UnlockRelation(pg_class_desc, AccessShareLock);
heap_close(pg_class_desc);
return return_tuple; return return_tuple;
} }
@ -508,7 +498,7 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
* open pg_attribute and begin a scan * 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); 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_endscan(pg_attribute_scan);
heap_close(pg_attribute_desc); heap_close(pg_attribute_desc, AccessShareLock);
} }
static void static void
@ -562,7 +552,7 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
constr->has_not_null = false; constr->has_not_null = false;
attrel = heap_openr(AttributeRelationName); attrel = heap_openr(AttributeRelationName, AccessShareLock);
for (i = 1; i <= relation->rd_rel->relnatts; i++) 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) 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 * 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_scan = heap_beginscan(pg_rewrite_desc, 0, SnapshotNow, 1, &key);
pg_rewrite_tupdesc = RelationGetDescr(pg_rewrite_desc); pg_rewrite_tupdesc = RelationGetDescr(pg_rewrite_desc);
@ -732,7 +722,7 @@ RelationBuildRuleLock(Relation relation)
* ---------------- * ----------------
*/ */
heap_endscan(pg_rewrite_scan); heap_endscan(pg_rewrite_scan);
heap_close(pg_rewrite_desc); heap_close(pg_rewrite_desc, AccessShareLock);
/* ---------------- /* ----------------
* form a RuleLock and insert into relation * form a RuleLock and insert into relation
@ -765,9 +755,9 @@ RelationBuildRuleLock(Relation relation)
* uint16 rd_refcnt; reference count * uint16 rd_refcnt; reference count
* Form_pg_am rd_am; AM tuple * Form_pg_am rd_am; AM tuple
* Form_pg_class rd_rel; RELATION tuple * Form_pg_class rd_rel; RELATION tuple
* Oid rd_id; relations's object id * Oid rd_id; relation's object id
* Pointer lockInfo; ptr. to misc. info. * LockInfoData rd_lockInfo; lock manager's info
* TupleDesc rd_att; tuple desciptor * TupleDesc rd_att; tuple descriptor
* *
* Note: rd_ismem (rel is in-memory only) is currently unused * Note: rd_ismem (rel is in-memory only) is currently unused
* by any part of the system. someday this will indicate that * by any part of the system. someday this will indicate that
@ -1048,14 +1038,18 @@ formrdesc(char *relationName,
*/ */
RelationGetRelid(relation) = relation->rd_att->attrs[0]->attrelid; RelationGetRelid(relation) = relation->rd_att->attrs[0]->attrelid;
/* ----------------
* initialize the relation lock manager information
* ----------------
*/
RelationInitLockInfo(relation); /* see lmgr.c */
/* ---------------- /* ----------------
* add new reldesc to relcache * add new reldesc to relcache
* ---------------- * ----------------
*/ */
RelationCacheInsert(relation); RelationCacheInsert(relation);
RelationInitLockInfo(relation);
/* /*
* Determining this requires a scan on pg_class, but to do the scan * 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 * the rdesc for pg_class must already exist. Therefore we must do
@ -1074,9 +1068,13 @@ formrdesc(char *relationName,
/* -------------------------------- /* --------------------------------
* RelationIdCacheGetRelation * RelationIdCacheGetRelation
* *
* only try to get the reldesc by looking up the cache * Lookup a reldesc by OID.
* do not go to the disk. this is used by BlockPrepareFile() * Only try to get the reldesc by looking up the cache
* and RelationIdGetRelation below. * 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 Relation
@ -1103,6 +1101,8 @@ RelationIdCacheGetRelation(Oid relationId)
/* -------------------------------- /* --------------------------------
* RelationNameCacheGetRelation * RelationNameCacheGetRelation
*
* As above, but lookup by name.
* -------------------------------- * --------------------------------
*/ */
static Relation static Relation
@ -1136,8 +1136,11 @@ RelationNameCacheGetRelation(char *relationName)
/* -------------------------------- /* --------------------------------
* RelationIdGetRelation * RelationIdGetRelation
* *
* return a relation descriptor based on its id. * Lookup a reldesc by OID; make one if not already in cache.
* return a cached value if possible *
* 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 Relation
@ -1176,8 +1179,7 @@ RelationIdGetRelation(Oid relationId)
/* -------------------------------- /* --------------------------------
* RelationNameGetRelation * RelationNameGetRelation
* *
* return a relation descriptor based on its name. * As above, but lookup by name.
* return a cached value if possible
* -------------------------------- * --------------------------------
*/ */
Relation Relation
@ -1289,7 +1291,6 @@ RelationFlushRelation(Relation *relationPtr,
/* Free all the subsidiary data structures of the relcache entry */ /* Free all the subsidiary data structures of the relcache entry */
FreeTupleDesc(relation->rd_att); FreeTupleDesc(relation->rd_att);
FreeTriggerDesc(relation); FreeTriggerDesc(relation);
pfree(RelationGetLockInfo(relation));
pfree(RelationGetForm(relation)); pfree(RelationGetForm(relation));
/* If we're really done with the relcache entry, blow it away. /* If we're really done with the relcache entry, blow it away.
@ -1530,10 +1531,10 @@ RelationRegisterRelation(Relation relation)
if (oldcxt != (MemoryContext) CacheCxt) if (oldcxt != (MemoryContext) CacheCxt)
elog(NOIND, "RelationRegisterRelation: WARNING: Context != CacheCxt"); elog(NOIND, "RelationRegisterRelation: WARNING: Context != CacheCxt");
RelationCacheInsert(relation);
RelationInitLockInfo(relation); RelationInitLockInfo(relation);
RelationCacheInsert(relation);
/* /*
* we've just created the relation. It is invisible to anyone else * we've just created the relation. It is invisible to anyone else
* before the transaction is committed. Setting rd_myxactonly allows * before the transaction is committed. Setting rd_myxactonly allows
@ -1692,7 +1693,7 @@ AttrDefaultFetch(Relation relation)
(RegProcedure) F_OIDEQ, (RegProcedure) F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(relation))); ObjectIdGetDatum(RelationGetRelid(relation)));
adrel = heap_openr(AttrDefaultRelationName); adrel = heap_openr(AttrDefaultRelationName, AccessShareLock);
irel = index_openr(AttrDefaultIndex); irel = index_openr(AttrDefaultIndex);
sd = index_beginscan(irel, false, 1, &skey); sd = index_beginscan(irel, false, 1, &skey);
tuple.t_data = NULL; tuple.t_data = NULL;
@ -1754,7 +1755,7 @@ AttrDefaultFetch(Relation relation)
index_endscan(sd); index_endscan(sd);
pfree(sd); pfree(sd);
index_close(irel); index_close(irel);
heap_close(adrel); heap_close(adrel, AccessShareLock);
} }
static void static void
@ -1779,7 +1780,7 @@ RelCheckFetch(Relation relation)
(RegProcedure) F_OIDEQ, (RegProcedure) F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(relation))); ObjectIdGetDatum(RelationGetRelid(relation)));
rcrel = heap_openr(RelCheckRelationName); rcrel = heap_openr(RelCheckRelationName, AccessShareLock);
irel = index_openr(RelCheckIndex); irel = index_openr(RelCheckIndex);
sd = index_beginscan(irel, false, 1, &skey); sd = index_beginscan(irel, false, 1, &skey);
tuple.t_data = NULL; tuple.t_data = NULL;
@ -1834,8 +1835,7 @@ RelCheckFetch(Relation relation)
index_endscan(sd); index_endscan(sd);
pfree(sd); pfree(sd);
index_close(irel); index_close(irel);
heap_close(rcrel); heap_close(rcrel, AccessShareLock);
} }
/* /*
@ -1929,9 +1929,6 @@ init_irels(void)
/* the file descriptor is not yet opened */ /* the file descriptor is not yet opened */
ird->rd_fd = -1; ird->rd_fd = -1;
/* lock info is not initialized */
ird->lockInfo = (char *) NULL;
/* next, read the access method tuple form */ /* next, read the access method tuple form */
if ((nread = FileRead(fd, (char *) &len, sizeof(len))) != sizeof(len)) if ((nread = FileRead(fd, (char *) &len, sizeof(len))) != sizeof(len))
{ {
@ -2038,8 +2035,9 @@ init_irels(void)
ird->rd_support = support; ird->rd_support = support;
RelationCacheInsert(ird);
RelationInitLockInfo(ird); RelationInitLockInfo(ird);
RelationCacheInsert(ird);
} }
} }

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* These routines allow the parser/planner/executor to perform * These routines allow the parser/planner/executor to perform
@ -575,11 +575,19 @@ SearchSysCacheGetAttribute(int cacheId,
Datum attributeValue; Datum attributeValue;
void *returnValue; 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; cacheName = cacheinfo[cacheId].name;
relation = heap_openr(cacheName, AccessShareLock);
tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
if (!HeapTupleIsValid(tp)) if (!HeapTupleIsValid(tp))
{ {
heap_close(relation, AccessShareLock);
#ifdef CACHEDEBUG #ifdef CACHEDEBUG
elog(DEBUG, elog(DEBUG,
"SearchSysCacheGetAttribute: Lookup in %s(%d) failed", "SearchSysCacheGetAttribute: Lookup in %s(%d) failed",
@ -588,8 +596,6 @@ SearchSysCacheGetAttribute(int cacheId,
return NULL; return NULL;
} }
relation = heap_openr(cacheName);
if (attributeNumber < 0 && if (attributeNumber < 0 &&
attributeNumber > FirstLowInvalidHeapAttributeNumber) attributeNumber > FirstLowInvalidHeapAttributeNumber)
{ {
@ -604,6 +610,7 @@ SearchSysCacheGetAttribute(int cacheId,
} }
else else
{ {
heap_close(relation, AccessShareLock);
elog(ERROR, elog(ERROR,
"SearchSysCacheGetAttribute: Bad attr # %d in %s(%d)", "SearchSysCacheGetAttribute: Bad attr # %d in %s(%d)",
attributeNumber, cacheName, cacheId); attributeNumber, cacheName, cacheId);
@ -617,11 +624,11 @@ SearchSysCacheGetAttribute(int cacheId,
if (isNull) if (isNull)
{ {
/* /*
* Used to be an elog(DEBUG, ...) here and a claim that it should * 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 * be a FATAL error, I don't think either is warranted -mer 6/9/92
*/ */
heap_close(relation, AccessShareLock);
return NULL; return NULL;
} }
@ -639,6 +646,6 @@ SearchSysCacheGetAttribute(int cacheId,
returnValue = (void *) tmp; returnValue = (void *) tmp;
} }
heap_close(relation); heap_close(relation, AccessShareLock);
return returnValue; return returnValue;
} }

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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 * 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, procedureTuple = SearchSysCacheTuple(PROOID,
ObjectIdGetDatum(procedureId), ObjectIdGetDatum(procedureId),
0, 0, 0); 0, 0, 0);
@ -71,36 +76,24 @@ fmgr_dynamic(Oid procedureId, int *pronargs)
procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple); procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
proname = procedureStruct->proname.data; proname = procedureStruct->proname.data;
pronargs_save = *pronargs = procedureStruct->pronargs; 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, probinattr = heap_getattr(procedureTuple,
Anum_pg_proc_probin, Anum_pg_proc_probin,
RelationGetDescr(rel), &isnull); RelationGetDescr(rel), &isnull);
if (!PointerIsValid(probinattr) /* || isnull */ ) if (!PointerIsValid(probinattr) /* || isnull */ )
{ {
heap_close(rel); heap_close(rel, AccessShareLock);
elog(ERROR, "fmgr: Could not extract probin for %u from %s", elog(ERROR, "fmgr: Could not extract probin for %u from %s",
procedureId, ProcedureRelationName); procedureId, ProcedureRelationName);
return (func_ptr) NULL; return (func_ptr) NULL;
} }
probinstring = textout((struct varlena *) probinattr); probinstring = textout((struct varlena *) probinattr);
heap_close(rel, AccessShareLock);
user_fn = handle_load(probinstring, proname); user_fn = handle_load(probinstring, proname);
pfree(probinstring);
procedureId_save = procedureId; procedureId_save = procedureId;
user_fn_save = user_fn; user_fn_save = user_fn;

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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; HeapScanDesc scan;
ScanKeyData scanKey; ScanKeyData scanKey;
dbrel = heap_openr(DatabaseRelationName); dbrel = heap_openr(DatabaseRelationName, AccessShareLock);
if (!RelationIsValid(dbrel))
elog(FATAL, "GetDatabaseInfo: cannot open relation \"%-.*s\"",
DatabaseRelationName);
ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_database_datname, ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_database_datname,
F_NAMEEQ, NameGetDatum(name)); F_NAMEEQ, NameGetDatum(name));
@ -71,6 +68,7 @@ GetDatabaseInfo(char *name, int4 *owner, char *path)
{ {
elog(NOTICE, "GetDatabaseInfo: %s entry not found %s", elog(NOTICE, "GetDatabaseInfo: %s entry not found %s",
DatabaseRelationName, name); DatabaseRelationName, name);
heap_close(dbrel, AccessShareLock);
return TRUE; return TRUE;
} }
@ -88,7 +86,7 @@ GetDatabaseInfo(char *name, int4 *owner, char *path)
memcpy(dbpath, VARDATA(dbtext), (VARSIZE(dbtext) - VARHDRSZ)); memcpy(dbpath, VARDATA(dbtext), (VARSIZE(dbtext) - VARHDRSZ));
*(dbpath + (VARSIZE(dbtext) - VARHDRSZ)) = '\0'; *(dbpath + (VARSIZE(dbtext) - VARHDRSZ)) = '\0';
heap_close(dbrel); heap_close(dbrel, AccessShareLock);
owner = palloc(sizeof(Oid)); owner = palloc(sizeof(Oid));
*owner = dbowner; *owner = dbowner;

View File

@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * 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/relscan.h"
#include "access/tupmacs.h" #include "access/tupmacs.h"
#include "storage/block.h" #include "storage/block.h"
#include "storage/lmgr.h"
#include "utils/rel.h" #include "utils/rel.h"
#include "utils/tqual.h" #include "utils/tqual.h"
@ -246,9 +247,9 @@ extern HeapAccessStatistics heap_access_stats; /* in stats.c */
/* heapam.c */ /* heapam.c */
extern Relation heap_open(Oid relationId); extern Relation heap_open(Oid relationId, LOCKMODE lockmode);
extern Relation heap_openr(char *relationName); extern Relation heap_openr(char *relationName, LOCKMODE lockmode);
extern void heap_close(Relation relation); extern void heap_close(Relation relation, LOCKMODE lockmode);
extern HeapScanDesc heap_beginscan(Relation relation, int atend, extern HeapScanDesc heap_beginscan(Relation relation, int atend,
Snapshot snapshot, unsigned nkeys, ScanKey key); Snapshot snapshot, unsigned nkeys, ScanKey key);
extern void heap_rescan(HeapScanDesc scan, bool scanFromEnd, ScanKey key); extern void heap_rescan(HeapScanDesc scan, bool scanFromEnd, ScanKey key);

View File

@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * 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 * NOTE
* If BUFFERPAGE0 is defined, then 0 will be used as a * 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) \ #define INIT_BUFFERTAG(a,xx_reln,xx_blockNum) \
( \ ( \
(a)->blockNum = xx_blockNum, \ (a)->blockNum = (xx_blockNum), \
(a)->relId = ((LockInfo)(xx_reln->lockInfo))->lockRelId \ (a)->relId = (xx_reln)->rd_lockInfo.lockRelId \
) )
#define BAD_BUFFER_ID(bid) ((bid<1) || (bid>(NBuffers))) #define BAD_BUFFER_ID(bid) ((bid<1) || (bid>(NBuffers)))

View File

@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * 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 "storage/lock.h"
#include "utils/rel.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 AccessShareLock 1 /* SELECT */
#define RowShareLock 2 /* SELECT FOR UPDATE */ #define RowShareLock 2 /* SELECT FOR UPDATE */
#define RowExclusiveLock 3 /* INSERT, UPDATE, DELETE */ #define RowExclusiveLock 3 /* INSERT, UPDATE, DELETE */
@ -27,21 +32,6 @@
extern LOCKMETHOD LockTableId; 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 LOCKMETHOD InitLockTable(void);
extern void RelationInitLockInfo(Relation relation); extern void RelationInitLockInfo(Relation relation);

View File

@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * 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 "rewrite/prs2lock.h"
#include "storage/fd.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 typedef struct Trigger
{ {
char *tgname; char *tgname;
@ -44,20 +64,21 @@ typedef struct TriggerDesc
Trigger *triggers; Trigger *triggers;
} TriggerDesc; } TriggerDesc;
typedef struct RelationData typedef struct RelationData
{ {
File rd_fd; /* open file descriptor */ File rd_fd; /* open file descriptor */
int rd_nblocks; /* number of blocks in rel */ int rd_nblocks; /* number of blocks in rel */
uint16 rd_refcnt; /* reference count */ 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_isnailed; /* rel is nailed in cache */
bool rd_isnoname; /* rel has no name */ bool rd_isnoname; /* rel has no name */
bool rd_nonameunlinked; /* noname rel already unlinked */ bool rd_nonameunlinked; /* noname rel already unlinked */
Form_pg_am rd_am; /* AM tuple */ Form_pg_am rd_am; /* AM tuple */
Form_pg_class rd_rel; /* RELATION tuple */ Form_pg_class rd_rel; /* RELATION tuple */
Oid rd_id; /* relations's object id */ Oid rd_id; /* relation's object id */
Pointer lockInfo; /* ptr. to misc. info. */ LockInfoData rd_lockInfo; /* lock manager's info for locking relation */
TupleDesc rd_att; /* tuple desciptor */ TupleDesc rd_att; /* tuple descriptor */
RuleLock *rd_rules; /* rewrite rules */ RuleLock *rd_rules; /* rewrite rules */
IndexStrategy rd_istrat; IndexStrategy rd_istrat;
RegProcedure *rd_support; RegProcedure *rd_support;
@ -66,6 +87,7 @@ typedef struct RelationData
typedef RelationData *Relation; typedef RelationData *Relation;
/* ---------------- /* ----------------
* RelationPtr is used in the executor to support index scans * RelationPtr is used in the executor to support index scans
* where we have to keep track of several index relations in an * where we have to keep track of several index relations in an
@ -74,7 +96,6 @@ typedef RelationData *Relation;
*/ */
typedef Relation *RelationPtr; typedef Relation *RelationPtr;
#define InvalidRelation ((Relation)NULL)
/* /*
* RelationIsValid * RelationIsValid
@ -82,6 +103,8 @@ typedef Relation *RelationPtr;
*/ */
#define RelationIsValid(relation) PointerIsValid(relation) #define RelationIsValid(relation) PointerIsValid(relation)
#define InvalidRelation ((Relation) NULL)
/* /*
* RelationGetSystemPort * RelationGetSystemPort
* Returns system port of a relation. * Returns system port of a relation.
@ -91,13 +114,6 @@ typedef Relation *RelationPtr;
*/ */
#define RelationGetSystemPort(relation) ((relation)->rd_fd) #define RelationGetSystemPort(relation) ((relation)->rd_fd)
/*
* RelationGetLockInfo
* Returns the lock information structure in the reldesc
*
*/
#define RelationGetLockInfo(relation) ((relation)->lockInfo)
/* /*
* RelationHasReferenceCountZero * RelationHasReferenceCountZero
* True iff relation reference count is zero. * True iff relation reference count is zero.
@ -112,13 +128,13 @@ typedef Relation *RelationPtr;
* RelationSetReferenceCount * RelationSetReferenceCount
* Sets relation reference count. * Sets relation reference count.
*/ */
#define RelationSetReferenceCount(relation,count) ((relation)->rd_refcnt = count) #define RelationSetReferenceCount(relation,count) ((relation)->rd_refcnt = (count))
/* /*
* RelationIncrementReferenceCount * RelationIncrementReferenceCount
* Increments relation reference count. * Increments relation reference count.
*/ */
#define RelationIncrementReferenceCount(relation) ((relation)->rd_refcnt += 1); #define RelationIncrementReferenceCount(relation) ((relation)->rd_refcnt += 1)
/* /*
* RelationDecrementReferenceCount * RelationDecrementReferenceCount
@ -135,7 +151,6 @@ typedef Relation *RelationPtr;
*/ */
#define RelationGetForm(relation) ((relation)->rd_rel) #define RelationGetForm(relation) ((relation)->rd_rel)
/* /*
* RelationGetRelid * RelationGetRelid
* *
@ -151,7 +166,6 @@ typedef Relation *RelationPtr;
*/ */
#define RelationGetFile(relation) ((relation)->rd_fd) #define RelationGetFile(relation) ((relation)->rd_fd)
/* /*
* RelationGetRelationName * RelationGetRelationName
* *
@ -160,21 +174,19 @@ typedef Relation *RelationPtr;
#define RelationGetRelationName(relation) (&(relation)->rd_rel->relname) #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) #define RelationGetNumberOfAttributes(relation) ((relation)->rd_rel->relnatts)
/* /*
* RelationGetDescr * RelationGetDescr
* Returns tuple descriptor for a relation. * Returns tuple descriptor for a relation.
*
* Note:
* Assumes relation descriptor is valid.
*/ */
#define RelationGetDescr(relation) ((relation)->rd_att) #define RelationGetDescr(relation) ((relation)->rd_att)
extern IndexStrategy RelationGetIndexStrategy(Relation relation); extern IndexStrategy RelationGetIndexStrategy(Relation relation);
extern void RelationSetIndexSupport(Relation relation, IndexStrategy strategy, extern void RelationSetIndexSupport(Relation relation, IndexStrategy strategy,