int ourpid = getpid();
char listen_name[NAMEDATALEN];
- lRel = heap_openr(ListenerRelationName);
+ lRel = heap_openr(ListenerRelationName, AccessShareLock);
tdesc = RelationGetDescr(lRel);
- LockRelation(lRel, AccessShareLock);
if (relname && (VARSIZE(relname) > VARHDRSZ)) {
len = MIN(VARSIZE(relname)-VARHDRSZ, NAMEDATALEN-1);
{
d = heap_getattr(lTuple, Anum_pg_listener_pid, tdesc, &isnull);
pid = DatumGetInt32(d);
-#ifdef HAVE_KILL
if ((pid == ourpid) || (kill(pid, SIGTSTP) == 0)) {
/* elog(NOTICE, "%d ok", pid); */
count++;
}
-#else
- count++;
-#endif
}
heap_endscan(sRel);
- UnlockRelation(lRel, AccessShareLock);
- heap_close(lRel);
+ heap_close(lRel, AccessShareLock);
return count;
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#include "catalog/index.h"
#include "catalog/pg_index.h"
#include "executor/executor.h"
+#include "miscadmin.h"
#include "utils/syscache.h"
TupleTableSlot *slot;
#endif
- Oid hrelid,
- irelid;
Node *pred,
*oldPred;
GISTSTATE giststate;
}
/*
- * Since we just inted the tuples in the heap, we update its stats in
- * pg_relation to guarantee that the planner takes advantage of the
- * index we just created. UpdateStats() does a
- * CommandinterIncrement(), which flushes changed entries from the
- * system relcache. The act of constructing an index changes these
- * heap and index tuples in the system catalogs, so they need to be
- * flushed. We close them to guarantee that they will be.
+ * Since we just counted the tuples in the heap, we update its stats
+ * in pg_class to guarantee that the planner takes advantage of the
+ * index we just created. But, only update statistics during
+ * normal index definitions, not for indices on system catalogs
+ * created during bootstrap processing. We must close the relations
+ * before updating statistics to guarantee that the relcache entries
+ * are flushed when we increment the command counter in UpdateStats().
+ * But we do not release any locks on the relations; those will be
+ * held until end of transaction.
*/
-
- hrelid = RelationGetRelid(heap);
- irelid = RelationGetRelid(index);
- heap_close(heap);
- index_close(index);
-
- UpdateStats(hrelid, nh, true);
- UpdateStats(irelid, ni, false);
-
- if (oldPred != NULL)
+ if (IsNormalProcessingMode())
{
- if (ni == nh)
- pred = NULL;
- UpdateIndexPredicate(irelid, oldPred, pred);
+ Oid hrelid = RelationGetRelid(heap);
+ Oid irelid = RelationGetRelid(index);
+
+ heap_close(heap, NoLock);
+ index_close(index);
+ UpdateStats(hrelid, nh, true);
+ UpdateStats(irelid, ni, false);
+ if (oldPred != NULL)
+ {
+ if (ni == nh)
+ pred = NULL;
+ UpdateIndexPredicate(irelid, oldPred, pred);
+ }
}
/* be tidy */
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.30 1999/07/17 20:16:38 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.31 1999/09/18 19:05:52 tgl Exp $
*
* NOTES
* This file contains only the public interface routines.
TupleTableSlot *slot;
#endif
- Oid hrelid,
- irelid;
Node *pred,
*oldPred;
/*
* Since we just counted the tuples in the heap, we update its stats
* in pg_class to guarantee that the planner takes advantage of the
- * index we just created. Finally, only update statistics during
+ * index we just created. But, only update statistics during
* normal index definitions, not for indices on system catalogs
* created during bootstrap processing. We must close the relations
- * before updatings statistics to guarantee that the relcache entries
+ * before updating statistics to guarantee that the relcache entries
* are flushed when we increment the command counter in UpdateStats().
+ * But we do not release any locks on the relations; those will be
+ * held until end of transaction.
*/
if (IsNormalProcessingMode())
{
- hrelid = RelationGetRelid(heap);
- irelid = RelationGetRelid(index);
- heap_close(heap);
+ Oid hrelid = RelationGetRelid(heap);
+ Oid irelid = RelationGetRelid(index);
+
+ heap_close(heap, NoLock);
index_close(index);
UpdateStats(hrelid, nhtups, true);
UpdateStats(irelid, nitups, false);
*
*
* 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
/* ----------------
* heap_open - open a heap relation by relationId
*
- * presently the relcache routines do all the work we need
- * to open/close heap relations.
+ * If lockmode is "NoLock", no lock is obtained on the relation,
+ * and the caller must check for a NULL return value indicating
+ * that no such relation exists.
+ * Otherwise, an error is raised if the relation does not exist,
+ * and the specified kind of lock is obtained on the relation.
* ----------------
*/
Relation
-heap_open(Oid relationId)
+heap_open(Oid relationId, LOCKMODE lockmode)
{
Relation r;
+ Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
+
/* ----------------
* increment access statistics
* ----------------
IncrHeapAccessStat(local_open);
IncrHeapAccessStat(global_open);
- r = (Relation) RelationIdGetRelation(relationId);
+ /* The relcache does all the real work... */
+ r = RelationIdGetRelation(relationId);
+ /* Under no circumstances will we return an index as a relation. */
if (RelationIsValid(r) && r->rd_rel->relkind == RELKIND_INDEX)
elog(ERROR, "%s is an index relation", r->rd_rel->relname.data);
+ if (lockmode == NoLock)
+ return r; /* caller must check RelationIsValid! */
+
+ if (! RelationIsValid(r))
+ elog(ERROR, "Relation %u does not exist", relationId);
+
+ LockRelation(r, lockmode);
+
return r;
}
/* ----------------
* heap_openr - open a heap relation by name
*
- * presently the relcache routines do all the work we need
- * to open/close heap relations.
+ * If lockmode is "NoLock", no lock is obtained on the relation,
+ * and the caller must check for a NULL return value indicating
+ * that no such relation exists.
+ * Otherwise, an error is raised if the relation does not exist,
+ * and the specified kind of lock is obtained on the relation.
* ----------------
*/
Relation
-heap_openr(char *relationName)
+heap_openr(char *relationName, LOCKMODE lockmode)
{
Relation r;
+ Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
+
/* ----------------
* increment access statistics
* ----------------
IncrHeapAccessStat(local_openr);
IncrHeapAccessStat(global_openr);
+ /* The relcache does all the real work... */
r = RelationNameGetRelation(relationName);
+ /* Under no circumstances will we return an index as a relation. */
if (RelationIsValid(r) && r->rd_rel->relkind == RELKIND_INDEX)
elog(ERROR, "%s is an index relation", r->rd_rel->relname.data);
+ if (lockmode == NoLock)
+ return r; /* caller must check RelationIsValid! */
+
+ if (! RelationIsValid(r))
+ elog(ERROR, "Relation '%s' does not exist", relationName);
+
+ LockRelation(r, lockmode);
+
return r;
}
/* ----------------
* heap_close - close a heap relation
*
- * presently the relcache routines do all the work we need
- * to open/close heap relations.
+ * If lockmode is not "NoLock", we first release the specified lock.
+ * Note that it is often sensible to hold a lock beyond heap_close;
+ * in that case, the lock is released automatically at xact end.
* ----------------
*/
void
-heap_close(Relation relation)
+heap_close(Relation relation, LOCKMODE lockmode)
{
+ Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
+
/* ----------------
* increment access statistics
* ----------------
IncrHeapAccessStat(local_close);
IncrHeapAccessStat(global_close);
+ if (lockmode != NoLock)
+ UnlockRelation(relation, lockmode);
+
+ /* The relcache does the real work... */
RelationClose(relation);
}
* sanity checks
* ----------------
*/
- if (RelationIsValid(relation) == false)
+ if (! RelationIsValid(relation))
elog(ERROR, "heap_beginscan: !RelationIsValid(relation)");
- LockRelation(relation, AccessShareLock);
-
- /* XXX someday assert SelfTimeQual if relkind == RELKIND_UNCATALOGED */
- if (relation->rd_rel->relkind == RELKIND_UNCATALOGED)
- snapshot = SnapshotSelf;
-
/* ----------------
* increment relation ref count while scanning relation
* ----------------
*/
RelationIncrementReferenceCount(relation);
+ /* ----------------
+ * Acquire AccessShareLock for the duration of the scan
+ *
+ * Note: we could get an SI inval message here and consequently have
+ * to rebuild the relcache entry. The refcount increment above
+ * ensures that we will rebuild it and not just flush it...
+ * ----------------
+ */
+ LockRelation(relation, AccessShareLock);
+
+ /* XXX someday assert SelfTimeQual if relkind == RELKIND_UNCATALOGED */
+ if (relation->rd_rel->relkind == RELKIND_UNCATALOGED)
+ snapshot = SnapshotSelf;
+
/* ----------------
* allocate and initialize scan descriptor
* ----------------
*/
unpinscan(scan);
+ /* ----------------
+ * Release AccessShareLock acquired by heap_beginscan()
+ * ----------------
+ */
+ UnlockRelation(scan->rs_rd, AccessShareLock);
+
/* ----------------
* decrement relation reference count and free scan descriptor storage
* ----------------
*/
RelationDecrementReferenceCount(scan->rs_rd);
- UnlockRelation(scan->rs_rd, AccessShareLock);
-
- pfree(scan); /* XXX */
+ pfree(scan);
}
/* ----------------
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.35 1999/07/16 04:58:28 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.36 1999/09/18 19:06:04 tgl Exp $
*
* INTERFACE ROUTINES
* index_open - open an index relation by relationId
* index_open - open an index relation by relationId
*
* presently the relcache routines do all the work we need
- * to open/close index relations.
+ * to open/close index relations. However, callers of index_open
+ * expect it to succeed, so we need to check for a failure return.
+ *
+ * Note: we acquire no lock on the index. An AccessShareLock is
+ * acquired by index_beginscan (and released by index_endscan).
* ----------------
*/
Relation
index_open(Oid relationId)
{
- return RelationIdGetRelation(relationId);
+ Relation r;
+
+ r = RelationIdGetRelation(relationId);
+
+ if (! RelationIsValid(r))
+ elog(ERROR, "Index %u does not exist", relationId);
+
+ if (r->rd_rel->relkind != RELKIND_INDEX)
+ elog(ERROR, "%s is not an index relation", r->rd_rel->relname.data);
+
+ return r;
}
/* ----------------
* index_openr - open a index relation by name
*
- * presently the relcache routines do all the work we need
- * to open/close index relations.
+ * As above, but lookup by name instead of OID.
* ----------------
*/
Relation
index_openr(char *relationName)
{
- return RelationNameGetRelation(relationName);
+ Relation r;
+
+ r = RelationNameGetRelation(relationName);
+
+ if (! RelationIsValid(r))
+ elog(ERROR, "Index '%s' does not exist", relationName);
+
+ if (r->rd_rel->relkind != RELKIND_INDEX)
+ elog(ERROR, "%s is not an index relation", r->rd_rel->relname.data);
+
+ return r;
}
/* ----------------
RELATION_CHECKS;
GET_REL_PROCEDURE(beginscan, ambeginscan);
+ RelationIncrementReferenceCount(relation);
+
+ /* ----------------
+ * Acquire AccessShareLock for the duration of the scan
+ *
+ * Note: we could get an SI inval message here and consequently have
+ * to rebuild the relcache entry. The refcount increment above
+ * ensures that we will rebuild it and not just flush it...
+ * ----------------
+ */
LockRelation(relation, AccessShareLock);
scandesc = (IndexScanDesc)
fmgr(procedure, scan);
+ /* Release lock and refcount acquired by index_beginscan */
+
UnlockRelation(scan->relation, AccessShareLock);
+
+ RelationDecrementReferenceCount(scan->relation);
}
/* ----------------
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
F_OIDEQ,
ObjectIdGetDatum(indexObjectId));
- relation = heap_openr(IndexRelationName);
+ relation = heap_openr(IndexRelationName, AccessShareLock);
scan = heap_beginscan(relation, false, SnapshotNow, 1, entry);
tuple = heap_getnext(scan, 0);
}
if (IsBootstrapProcessingMode())
{
heap_endscan(scan);
- heap_close(relation);
+ heap_close(relation, AccessShareLock);
}
/* if support routines exist for this access method, load them */
ScanKeyEntryInitialize(&entry[1], 0, Anum_pg_amproc_amopclaid,
F_OIDEQ, 0);
- relation = heap_openr(AccessMethodProcedureRelationName);
+ relation = heap_openr(AccessMethodProcedureRelationName,
+ AccessShareLock);
for (attributeNumber = 1; attributeNumber <= maxAttributeNumber;
attributeNumber++)
heap_endscan(scan);
}
- heap_close(relation);
+ heap_close(relation, AccessShareLock);
}
ScanKeyEntryInitialize(&entry[0], 0,
Anum_pg_amop_amopclaid,
F_OIDEQ, 0);
- relation = heap_openr(AccessMethodOperatorRelationName);
- operatorRelation = heap_openr(OperatorRelationName);
+ relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock);
+ operatorRelation = heap_openr(OperatorRelationName, AccessShareLock);
for (attributeNumber = maxAttributeNumber; attributeNumber > 0;
attributeNumber--)
heap_endscan(scan);
}
- heap_close(operatorRelation);
- heap_close(relation);
+ heap_close(operatorRelation, AccessShareLock);
+ heap_close(relation, AccessShareLock);
}
/* ----------------
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.45 1999/07/17 20:16:43 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.46 1999/09/18 19:06:10 tgl Exp $
*
* NOTES
* This file contains only the public interface routines.
TupleTableSlot *slot = (TupleTableSlot *) NULL;
#endif
- Oid hrelid,
- irelid;
Node *pred,
*oldPred;
void *spool = (void *) NULL;
/*
* Since we just counted the tuples in the heap, we update its stats
* in pg_class to guarantee that the planner takes advantage of the
- * index we just created. Finally, only update statistics during
+ * index we just created. But, only update statistics during
* normal index definitions, not for indices on system catalogs
* created during bootstrap processing. We must close the relations
- * before updatings statistics to guarantee that the relcache entries
+ * before updating statistics to guarantee that the relcache entries
* are flushed when we increment the command counter in UpdateStats().
+ * But we do not release any locks on the relations; those will be
+ * held until end of transaction.
*/
if (IsNormalProcessingMode())
{
- hrelid = RelationGetRelid(heap);
- irelid = RelationGetRelid(index);
- heap_close(heap);
+ Oid hrelid = RelationGetRelid(heap);
+ Oid irelid = RelationGetRelid(index);
+
+ heap_close(heap, NoLock);
index_close(index);
UpdateStats(hrelid, nhtups, true);
UpdateStats(irelid, nitups, false);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#include "access/rtree.h"
#include "catalog/index.h"
#include "executor/executor.h"
+#include "miscadmin.h"
#include "utils/geo_decls.h"
TupleTableSlot *slot;
#endif
- Oid hrelid,
- irelid;
Node *pred,
*oldPred;
RTSTATE rtState;
/*
* Since we just counted the tuples in the heap, we update its stats
- * in pg_relation to guarantee that the planner takes advantage of the
- * index we just created. UpdateStats() does a
- * CommandCounterIncrement(), which flushes changed entries from the
- * system relcache. The act of constructing an index changes these
- * heap and index tuples in the system catalogs, so they need to be
- * flushed. We close them to guarantee that they will be.
+ * in pg_class to guarantee that the planner takes advantage of the
+ * index we just created. But, only update statistics during
+ * normal index definitions, not for indices on system catalogs
+ * created during bootstrap processing. We must close the relations
+ * before updating statistics to guarantee that the relcache entries
+ * are flushed when we increment the command counter in UpdateStats().
+ * But we do not release any locks on the relations; those will be
+ * held until end of transaction.
*/
-
- hrelid = RelationGetRelid(heap);
- irelid = RelationGetRelid(index);
- heap_close(heap);
- index_close(index);
-
- UpdateStats(hrelid, nh, true);
- UpdateStats(irelid, ni, false);
-
- if (oldPred != NULL)
+ if (IsNormalProcessingMode())
{
- if (ni == nh)
- pred = NULL;
- UpdateIndexPredicate(irelid, oldPred, pred);
+ Oid hrelid = RelationGetRelid(heap);
+ Oid irelid = RelationGetRelid(index);
+
+ heap_close(heap, NoLock);
+ index_close(index);
+ UpdateStats(hrelid, nh, true);
+ UpdateStats(irelid, ni, false);
+ if (oldPred != NULL)
+ {
+ if (ni == nh)
+ pred = NULL;
+ UpdateIndexPredicate(irelid, oldPred, pred);
+ }
}
/* be tidy */
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.31 1999/08/08 20:12:52 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.32 1999/09/18 19:06:21 tgl Exp $
*
* NOTES
* This file contains the high level access-method interface to the
* (these are created by amiint so they are guaranteed to exist)
* ----------------
*/
- logRelation = heap_openr(LogRelationName);
- VariableRelation = heap_openr(VariableRelationName);
+ logRelation = heap_openr(LogRelationName, NoLock);
+ Assert(logRelation != NULL);
+ VariableRelation = heap_openr(VariableRelationName, NoLock);
+ Assert(VariableRelation != NULL);
+
/* ----------------
* XXX TransactionLogUpdate requires that LogRelation
* is valid so we temporarily set it so we can initialize
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* ----------------
*/
if (!RelationIsValid(VariableRelation))
- VariableRelation = heap_openr(VariableRelationName);
+ VariableRelation = heap_openr(VariableRelationName, NoLock);
/* ----------------
* get a new block of prefetched object ids.
* Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.66 1999/07/19 02:27:04 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.67 1999/09/18 19:06:27 tgl Exp $
*
*-------------------------------------------------------------------------
*/
if (Typ == (struct typmap **) NULL)
{
StartPortalAllocMode(DefaultAllocMode, 0);
- rel = heap_openr(TypeRelationName);
+ rel = heap_openr(TypeRelationName, NoLock);
+ Assert(rel);
scan = heap_beginscan(rel, 0, SnapshotNow, 0, (ScanKey) NULL);
i = 0;
while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
sizeof((*app)->am_typ));
}
heap_endscan(scan);
- heap_close(rel);
+ heap_close(rel, NoLock);
EndPortalAllocMode();
}
printf("Amopen: relation %s. attrsize %d\n", relname ? relname : "(null)",
(int) ATTRIBUTE_TUPLE_SIZE);
- reldesc = heap_openr(relname);
+ reldesc = heap_openr(relname, NoLock);
Assert(reldesc);
numattr = reldesc->rd_rel->relnatts;
for (i = 0; i < numattr; i++)
{
if (!Quiet)
printf("Amclose: relation %s.\n", relname ? relname : "(null)");
- heap_close(reldesc);
+ heap_close(reldesc, NoLock);
reldesc = (Relation) NULL;
}
}
proc_exit(1);
}
if (reldesc != (Relation) NULL)
- heap_close(reldesc);
+ heap_close(reldesc, NoLock);
CommitTransactionCommand();
proc_exit(Warnings);
}
}
if (DebugMode)
printf("bootstrap.c: External Type: %s\n", type);
- rel = heap_openr(TypeRelationName);
+ rel = heap_openr(TypeRelationName, NoLock);
+ Assert(rel);
scan = heap_beginscan(rel, 0, SnapshotNow, 0, (ScanKey) NULL);
i = 0;
while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
sizeof((*app)->am_typ));
}
heap_endscan(scan);
- heap_close(rel);
+ heap_close(rel, NoLock);
return gettype(type);
}
elog(ERROR, "Error: unknown type '%s'.\n", type);
for (; ILHead != (IndexList *) NULL; ILHead = ILHead->il_next)
{
- heap = heap_openr(ILHead->il_heap);
+ heap = heap_openr(ILHead->il_heap, NoLock);
+ Assert(heap);
ind = index_openr(ILHead->il_ind);
+ Assert(ind);
index_build(heap, ind, ILHead->il_natts, ILHead->il_attnos,
ILHead->il_nparams, ILHead->il_params, ILHead->il_finfo,
ILHead->il_predInfo);
+ /* In normal processing mode, index_build would close the heap
+ * and index, but in bootstrap mode it will not.
+ */
/*
* All of the rest of this routine is needed only because in
*
* -mer
*/
- heap = heap_openr(ILHead->il_heap);
-
if (!BootstrapAlreadySeen(RelationGetRelid(heap)))
UpdateStats(RelationGetRelid(heap), 0, true);
+
+ /* XXX Probably we ought to close the heap and index here? */
}
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.27 1999/07/30 18:09:44 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.28 1999/09/18 19:06:33 tgl Exp $
*
* NOTES
* See acl.h.
* We can't use the syscache here, since we need to do a heap_replace on
* the tuple we find.
*/
- relation = heap_openr(RelationRelationName);
- if (!RelationIsValid(relation))
- elog(ERROR, "ChangeAcl: could not open '%s'??",
- RelationRelationName);
+ relation = heap_openr(RelationRelationName, RowExclusiveLock);
tuple = SearchSysCacheTuple(RELNAME,
PointerGetDatum(relname),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
{
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
elog(ERROR, "ChangeAcl: class \"%s\" not found",
relname);
- return;
}
if (!heap_attisnull(tuple, Anum_pg_class_relacl))
CatalogIndexInsert(idescs, Num_pg_class_indices, relation, tuple);
CatalogCloseIndices(Num_pg_class_indices, idescs);
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
if (free_old_acl)
pfree(old_acl);
pfree(new_acl);
AclId *aidp;
int32 found = 0;
- relation = heap_openr(GroupRelationName);
- if (!RelationIsValid(relation))
- {
- elog(NOTICE, "in_group: could not open \"%s\"??",
- GroupRelationName);
- return 0;
- }
+ relation = heap_openr(GroupRelationName, RowExclusiveLock);
tuple = SearchSysCacheTuple(GROSYSID,
ObjectIdGetDatum(gid),
0, 0, 0);
}
else
elog(NOTICE, "in_group: group %d not found", gid);
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
return found;
}
}
#ifndef ACLDEBUG
+ relation = heap_openr(RelationRelationName, RowExclusiveLock);
tuple = SearchSysCacheTuple(RELNAME,
PointerGetDatum(relname),
0, 0, 0);
{
elog(ERROR, "pg_aclcheck: class \"%s\" not found",
relname);
- /* an elog(ERROR) kills us, so no need to return anything. */
}
if (!heap_attisnull(tuple, Anum_pg_class_relacl))
{
- relation = heap_openr(RelationRelationName);
tmp = (Acl *) heap_getattr(tuple,
Anum_pg_class_relacl,
RelationGetDescr(relation),
(bool *) NULL);
acl = makeacl(ACL_NUM(tmp));
memmove((char *) acl, (char *) tmp, ACL_SIZE(tmp));
- heap_close(relation);
}
else
{
*/
int4 ownerId;
- relation = heap_openr(RelationRelationName);
ownerId = (int4) heap_getattr(tuple,
Anum_pg_class_relowner,
RelationGetDescr(relation),
(bool *) NULL);
acl = aclownerdefault(relname, (AclId) ownerId);
- heap_close(relation);
}
+ heap_close(relation, RowExclusiveLock);
#else
- { /* This is why the syscache is great... */
- static ScanKeyData relkey[1] = {
- {0, Anum_pg_class_relname, F_NAMEEQ}
- };
-
- relation = heap_openr(RelationRelationName);
- if (!RelationIsValid(relation))
- {
- elog(NOTICE, "pg_checkacl: could not open \"%-.*s\"??",
- RelationRelationName);
- return ACLCHECK_NO_CLASS;
- }
- tuple = SearchSysCacheTuple(RELNAME,
- PointerGetDatum(relname),
- 0, 0, 0);
- if (HeapTupleIsValid(tuple) &&
- !heap_attisnull(tuple, Anum_pg_class_relacl))
- {
- tmp = (Acl *) heap_getattr(tuple,
- Anum_pg_class_relacl,
- RelationGetDescr(relation),
- (bool *) NULL);
- acl = makeacl(ACL_NUM(tmp));
- memmove((char *) acl, (char *) tmp, ACL_SIZE(tmp));
- }
- heap_close(relation);
+ relation = heap_openr(RelationRelationName, RowExclusiveLock);
+ tuple = SearchSysCacheTuple(RELNAME,
+ PointerGetDatum(relname),
+ 0, 0, 0);
+ if (HeapTupleIsValid(tuple) &&
+ !heap_attisnull(tuple, Anum_pg_class_relacl))
+ {
+ tmp = (Acl *) heap_getattr(tuple,
+ Anum_pg_class_relacl,
+ RelationGetDescr(relation),
+ (bool *) NULL);
+ acl = makeacl(ACL_NUM(tmp));
+ memmove((char *) acl, (char *) tmp, ACL_SIZE(tmp));
}
+ heap_close(relation, RowExclusiveLock);
#endif
result = aclcheck(relname, acl, id, (AclIdType) ACL_IDTYPE_UID, mode);
if (acl)
*
*
* 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
/* ----------------
* allocate a new relation descriptor.
- *
- * XXX the length computation may be incorrect, handle elsewhere
* ----------------
*/
len = sizeof(RelationData);
ScanKeyData key;
HeapScanDesc pg_class_scan;
- pg_class_desc = heap_openr(RelationRelationName);
+ pg_class_desc = heap_openr(RelationRelationName, AccessShareLock);
/* ----------------
* At bootstrap time, we have to do this the hard way. Form the
heap_endscan(pg_class_scan);
- heap_close(pg_class_desc);
+ heap_close(pg_class_desc, AccessShareLock);
}
return relid;
}
* open pg_attribute
* ----------------
*/
- rel = heap_openr(AttributeRelationName);
+ rel = heap_openr(AttributeRelationName, RowExclusiveLock);
/* -----------------
* Check if we have any indices defined on pg_attribute.
* -----------------
*/
- Assert(rel);
- Assert(rel->rd_rel);
hasindex = RelationGetForm(rel)->relhasindex;
if (hasindex)
CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
dpp++;
}
- heap_close(rel);
+ heap_close(rel, RowExclusiveLock);
/*
* close pg_attribute indices
* now update the information in pg_class.
* ----------------
*/
- pg_class_desc = heap_openr(RelationRelationName);
+ pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock);
AddNewRelationTuple(pg_class_desc,
new_rel_desc,
* SOMEDAY: fill the STATISTIC relation properly.
* ----------------
*/
- heap_close(new_rel_desc);
- heap_close(pg_class_desc);
+ heap_close(new_rel_desc, NoLock); /* do not unlock till end of xact */
+ heap_close(pg_class_desc, RowExclusiveLock);
return new_rel_oid;
}
* open pg_inherits
* ----------------
*/
- catalogRelation = heap_openr(InheritsRelationName);
+ catalogRelation = heap_openr(InheritsRelationName, RowExclusiveLock);
/* ----------------
* form a scan key for the subclasses of this class
tuple = heap_getnext(scan, 0);
if (HeapTupleIsValid(tuple))
{
+ Oid subclass = ((Form_pg_inherits) GETSTRUCT(tuple))->inhrel;
+
heap_endscan(scan);
- heap_close(catalogRelation);
+ heap_close(catalogRelation, RowExclusiveLock);
elog(ERROR, "Relation '%u' inherits '%s'",
- ((Form_pg_inherits) GETSTRUCT(tuple))->inhrel,
- RelationGetRelationName(relation));
+ subclass, RelationGetRelationName(relation));
}
+ heap_endscan(scan);
/* ----------------
* If we get here, it means the relation has no subclasses
}
heap_endscan(scan);
- heap_close(catalogRelation);
+ heap_close(catalogRelation, RowExclusiveLock);
/* ----------------
* now remove dead IPL tuples
* ----------------
*/
- catalogRelation = heap_openr(InheritancePrecidenceListRelationName);
+ catalogRelation = heap_openr(InheritancePrecidenceListRelationName,
+ RowExclusiveLock);
entry.sk_attno = Anum_pg_ipl_iplrel;
heap_delete(catalogRelation, &tuple->t_self, NULL);
heap_endscan(scan);
- heap_close(catalogRelation);
+ heap_close(catalogRelation, RowExclusiveLock);
}
/* --------------------------------
HeapScanDesc scan;
ScanKeyData entry;
- indexRelation = heap_openr(IndexRelationName);
+ indexRelation = heap_openr(IndexRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_index_indrelid,
F_OIDEQ,
index_destroy(((Form_pg_index) GETSTRUCT(tuple))->indexrelid);
heap_endscan(scan);
- heap_close(indexRelation);
+ heap_close(indexRelation, RowExclusiveLock);
}
/* --------------------------------
* open pg_class
* ----------------
*/
- pg_class_desc = heap_openr(RelationRelationName);
+ pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock);
tup = SearchSysCacheTupleCopy(RELOID,
ObjectIdGetDatum(rel->rd_att->attrs[0]->attrelid),
0, 0, 0);
if (!HeapTupleIsValid(tup))
{
- heap_close(pg_class_desc);
+ heap_close(pg_class_desc, RowExclusiveLock);
elog(ERROR, "Relation '%s' does not exist",
&rel->rd_rel->relname);
}
heap_delete(pg_class_desc, &tup->t_self, NULL);
pfree(tup);
- heap_close(pg_class_desc);
+ heap_close(pg_class_desc, RowExclusiveLock);
}
/* --------------------------------
* open pg_attribute
* ----------------
*/
- pg_attribute_desc = heap_openr(AttributeRelationName);
-
- /* -----------------
- * Get a write lock _before_ getting the read lock in the scan
- * ----------------
- */
- LockRelation(pg_attribute_desc, AccessExclusiveLock);
+ pg_attribute_desc = heap_openr(AttributeRelationName, RowExclusiveLock);
for (attnum = FirstLowInvalidHeapAttributeNumber + 1;
attnum <= rel->rd_att->natts;
}
}
- /* ----------------
- * Release the write lock
- * ----------------
- */
- UnlockRelation(pg_attribute_desc, AccessExclusiveLock);
- heap_close(pg_attribute_desc);
+ heap_close(pg_attribute_desc, RowExclusiveLock);
}
/* --------------------------------
* 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
if (!HeapTupleIsValid(tup))
{
heap_endscan(pg_type_scan);
- heap_close(pg_type_desc);
+ heap_close(pg_type_desc, RowExclusiveLock);
elog(ERROR, "DeleteTypeTuple: %s type nonexistent",
&rel->rd_rel->relname);
}
*/
typoid = tup->t_data->t_oid;
- pg_attribute_desc = heap_openr(AttributeRelationName);
+ pg_attribute_desc = heap_openr(AttributeRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&attkey,
0,
{
Oid relid = ((Form_pg_attribute) GETSTRUCT(atttup))->attrelid;
- heap_endscan(pg_type_scan);
- heap_close(pg_type_desc);
heap_endscan(pg_attribute_scan);
- heap_close(pg_attribute_desc);
+ heap_close(pg_attribute_desc, RowExclusiveLock);
+ heap_endscan(pg_type_scan);
+ heap_close(pg_type_desc, RowExclusiveLock);
elog(ERROR, "DeleteTypeTuple: att of type %s exists in relation %u",
&rel->rd_rel->relname, relid);
}
heap_endscan(pg_attribute_scan);
- heap_close(pg_attribute_desc);
+ heap_close(pg_attribute_desc, RowExclusiveLock);
/* ----------------
* Ok, it's safe so we delete the relation tuple
heap_delete(pg_type_desc, &tup->t_self, NULL);
heap_endscan(pg_type_scan);
- heap_close(pg_type_desc);
+ heap_close(pg_type_desc, RowExclusiveLock);
}
/* --------------------------------
bool istemp = (get_temp_rel_by_name(relname) != NULL);
/* ----------------
- * first open the relation. if the relation doesn't exist,
- * heap_openr() returns NULL.
+ * Open and lock the relation.
* ----------------
*/
- rel = heap_openr(relname);
- if (rel == NULL)
- elog(ERROR, "Relation '%s' does not exist", relname);
-
- LockRelation(rel, AccessExclusiveLock);
+ rel = heap_openr(relname, AccessExclusiveLock);
rid = rel->rd_id;
/* ----------------
* ----------------
*/
/* allow temp of pg_class? Guess so. */
- if (!istemp &&
- !allowSystemTableMods && IsSystemRelationName(RelationGetRelationName(rel)->data))
+ if (!istemp && !allowSystemTableMods &&
+ IsSystemRelationName(RelationGetRelationName(rel)->data))
elog(ERROR, "System relation '%s' cannot be destroyed",
&rel->rd_rel->relname);
rel->rd_nonameunlinked = TRUE;
- UnlockRelation(rel, AccessExclusiveLock);
-
- heap_close(rel);
+ /*
+ * Close relcache entry, but *keep* AccessExclusiveLock on the
+ * relation until transaction commit. This ensures no one else
+ * will try to do something with the doomed relation.
+ */
+ heap_close(rel, NoLock);
/* ----------------
* flush the relation from the relcache
if (!(rel->rd_isnoname) || !(rel->rd_nonameunlinked))
smgrunlink(DEFAULT_SMGR, rel);
rel->rd_nonameunlinked = TRUE;
- heap_close(rel);
+ heap_close(rel, NoLock);
RemoveFromNoNameRelList(rel);
}
values[Anum_pg_attrdef_adnum - 1] = attrdef->adnum;
values[Anum_pg_attrdef_adbin - 1] = PointerGetDatum(textin(attrdef->adbin));
values[Anum_pg_attrdef_adsrc - 1] = PointerGetDatum(textin(attrdef->adsrc));
- adrel = heap_openr(AttrDefaultRelationName);
+ adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
tuple = heap_formtuple(adrel->rd_att, values, nulls);
CatalogOpenIndices(Num_pg_attrdef_indices, Name_pg_attrdef_indices, idescs);
heap_insert(adrel, tuple);
CatalogIndexInsert(idescs, Num_pg_attrdef_indices, adrel, tuple);
CatalogCloseIndices(Num_pg_attrdef_indices, idescs);
- heap_close(adrel);
+ heap_close(adrel, RowExclusiveLock);
pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
pfree(DatumGetPointer(values[Anum_pg_attrdef_adsrc - 1]));
values[Anum_pg_relcheck_rcname - 1] = PointerGetDatum(namein(check->ccname));
values[Anum_pg_relcheck_rcbin - 1] = PointerGetDatum(textin(check->ccbin));
values[Anum_pg_relcheck_rcsrc - 1] = PointerGetDatum(textin(check->ccsrc));
- rcrel = heap_openr(RelCheckRelationName);
+ rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock);
tuple = heap_formtuple(rcrel->rd_att, values, nulls);
CatalogOpenIndices(Num_pg_relcheck_indices, Name_pg_relcheck_indices, idescs);
heap_insert(rcrel, tuple);
CatalogIndexInsert(idescs, Num_pg_relcheck_indices, rcrel, tuple);
CatalogCloseIndices(Num_pg_relcheck_indices, idescs);
- heap_close(rcrel);
+ heap_close(rcrel, RowExclusiveLock);
pfree(DatumGetPointer(values[Anum_pg_relcheck_rcname - 1]));
pfree(DatumGetPointer(values[Anum_pg_relcheck_rcbin - 1]));
pfree(DatumGetPointer(values[Anum_pg_relcheck_rcsrc - 1]));
pfree(tuple);
-
- return;
}
static void
ScanKeyData key;
HeapTuple tup;
- adrel = heap_openr(AttrDefaultRelationName);
+ adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&key, 0, Anum_pg_attrdef_adrelid,
F_OIDEQ, rel->rd_id);
- LockRelation(adrel, AccessExclusiveLock);
-
adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key);
while (HeapTupleIsValid(tup = heap_getnext(adscan, 0)))
heap_delete(adrel, &tup->t_self, NULL);
heap_endscan(adscan);
-
- UnlockRelation(adrel, AccessExclusiveLock);
- heap_close(adrel);
-
+ heap_close(adrel, RowExclusiveLock);
}
static void
ScanKeyData key;
HeapTuple tup;
- rcrel = heap_openr(RelCheckRelationName);
+ rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&key, 0, Anum_pg_relcheck_rcrelid,
F_OIDEQ, rel->rd_id);
- LockRelation(rcrel, AccessExclusiveLock);
-
rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key);
while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0)))
heap_delete(rcrel, &tup->t_self, NULL);
heap_endscan(rcscan);
-
- UnlockRelation(rcrel, AccessExclusiveLock);
- heap_close(rcrel);
-
+ heap_close(rcrel, RowExclusiveLock);
}
static void
if (constr->num_check > 0)
RemoveRelCheck(rel);
-
- return;
}
*
*
* 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
* fetch the desired access method tuple
* ----------------
*/
- pg_am_desc = heap_openr(AccessMethodRelationName);
+ pg_am_desc = heap_openr(AccessMethodRelationName, AccessShareLock);
pg_am_scan = heap_beginscan(pg_am_desc, 0, SnapshotNow, 1, &key);
pg_am_tuple = heap_getnext(pg_am_scan, 0);
if (!HeapTupleIsValid(pg_am_tuple))
{
heap_endscan(pg_am_scan);
- heap_close(pg_am_desc);
+ heap_close(pg_am_desc, AccessShareLock);
return NULL;
}
memcpy(aform, GETSTRUCT(pg_am_tuple), sizeof *aform);
heap_endscan(pg_am_scan);
- heap_close(pg_am_desc);
+ heap_close(pg_am_desc, AccessShareLock);
return aform;
}
Oid tupleOid;
Relation idescs[Num_pg_class_indices];
- pg_class = heap_openr(RelationRelationName);
+ pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
/* XXX Natts_pg_class_fixed is a hack - see pg_class.h */
tuple = heap_addheader(Natts_pg_class_fixed,
tupleOid = tuple->t_data->t_oid;
pfree(tuple);
- heap_close(pg_class);
+ heap_close(pg_class, RowExclusiveLock);
return tupleOid;
}
* XXX ADD INDEXING
* ----------------
*/
- pg_attribute = heap_openr(AttributeRelationName);
+ pg_attribute = heap_openr(AttributeRelationName, RowExclusiveLock);
/* ----------------
* initialize *null, *replace and *value
if (cur_tuple)
pfree(cur_tuple);
- heap_close(pg_attribute);
+ heap_close(pg_attribute, RowExclusiveLock);
if (hasind)
CatalogCloseIndices(Num_pg_attr_indices, idescs);
* 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
* close the relation and free the tuple
* ----------------
*/
- heap_close(pg_index);
+ heap_close(pg_index, RowExclusiveLock);
pfree(predText);
pfree(indexForm);
pfree(tuple);
predText = (text *) fmgr(F_TEXTIN, "");
/* open the index system catalog relation */
- pg_index = heap_openr(IndexRelationName);
+ pg_index = heap_openr(IndexRelationName, RowExclusiveLock);
tuple = SearchSysCacheTuple(INDEXRELID,
ObjectIdGetDatum(indexoid),
heap_replace(pg_index, &newtup->t_self, newtup, NULL);
pfree(newtup);
- heap_close(pg_index);
+ heap_close(pg_index, RowExclusiveLock);
pfree(predText);
}
*/
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
* the index yet. We'll be creating more indices and classes later,
* so we delay filling them in until just before we're done with
* bootstrapping. Otherwise, we call the routine that constructs the
- * index. The heap and index relations are closed by index_build().
+ * index.
+ *
+ * In normal processing mode, the heap and index relations are closed
+ * by index_build() --- but we continue to hold the ShareLock on the
+ * heap that we acquired above, until end of transaction.
*/
if (IsBootstrapProcessingMode())
{
index_register(heapRelationName, indexRelationName, numatts, attNums,
parameterCount, parameter, funcInfo, predInfo);
+ /* XXX shouldn't we close the heap and index rels here? */
}
else
{
- heapRelation = heap_openr(heapRelationName);
index_build(heapRelation, indexRelation, numatts, attNums,
parameterCount, parameter, funcInfo, predInfo);
}
Assert(OidIsValid(indexId));
- /* Open now to obtain lock by referencing table? bjm */
userindexRelation = index_open(indexId);
+ /*
+ * Get exclusive lock to ensure no one else is scanning this index.
+ */
+ LockRelation(userindexRelation, AccessExclusiveLock);
+
/* ----------------
* We do not allow DROP INDEX within a transaction block, because
* if the transaction is later rolled back there would be no way to
* fix RELATION relation
* ----------------
*/
- relationRelation = heap_openr(RelationRelationName);
+ relationRelation = heap_openr(RelationRelationName, RowExclusiveLock);
tuple = SearchSysCacheTupleCopy(RELOID,
ObjectIdGetDatum(indexId),
heap_delete(relationRelation, &tuple->t_self, NULL);
pfree(tuple);
- heap_close(relationRelation);
+ heap_close(relationRelation, RowExclusiveLock);
/* ----------------
* fix ATTRIBUTE relation
* ----------------
*/
- attributeRelation = heap_openr(AttributeRelationName);
+ attributeRelation = heap_openr(AttributeRelationName, RowExclusiveLock);
attnum = 1; /* indexes start at 1 */
pfree(tuple);
attnum++;
}
- heap_close(attributeRelation);
+ heap_close(attributeRelation, RowExclusiveLock);
/* does something only if it is a temp index */
remove_temp_relation(indexId);
* fix INDEX relation
* ----------------
*/
+ indexRelation = heap_openr(IndexRelationName, RowExclusiveLock);
+
tuple = SearchSysCacheTupleCopy(INDEXRELID,
ObjectIdGetDatum(indexId),
0, 0, 0);
Assert(HeapTupleIsValid(tuple));
- indexRelation = heap_openr(IndexRelationName);
-
heap_delete(indexRelation, &tuple->t_self, NULL);
pfree(tuple);
- heap_close(indexRelation);
+ heap_close(indexRelation, RowExclusiveLock);
/*
* flush cache and physically remove the file
elog(ERROR, "index_destroy: unlink: %m");
index_close(userindexRelation);
- RelationForgetRelation(RelationGetRelid(userindexRelation));
+
+ RelationForgetRelation(indexId);
}
/* ----------------------------------------------------------------
* ----------------
*/
+ /*
+ * Can't use heap_open here since we don't know if it's an index...
+ */
whichRel = RelationIdGetRelation(relid);
if (!RelationIsValid(whichRel))
elog(ERROR, "UpdateStats: cannot open relation id %u", relid);
+ LockRelation(whichRel, ShareLock);
+
/* ----------------
* Find the RELATION relation tuple for the given relation.
* ----------------
*/
- pg_class = heap_openr(RelationRelationName);
+ pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
if (!RelationIsValid(pg_class))
elog(ERROR, "UpdateStats: could not open RELATION relation");
{
if (IsBootstrapProcessingMode())
heap_endscan(pg_class_scan);
- heap_close(pg_class);
+ heap_close(pg_class, RowExclusiveLock);
elog(ERROR, "UpdateStats: cannot scan RELATION relation");
}
else
heap_endscan(pg_class_scan);
- heap_close(pg_class);
- heap_close(whichRel);
+ heap_close(pg_class, RowExclusiveLock);
+ /* Cheating a little bit since we didn't open it with heap_open... */
+ heap_close(whichRel, ShareLock);
}
pfree(datum);
/*
- * Okay, now update the reltuples and relpages statistics for both the
- * heap relation and the index. These statistics are used by the
- * planner to choose a scan type. They are maintained generally by
- * the vacuum daemon, but we update them here to make the index useful
- * as soon as possible.
- */
- UpdateStats(RelationGetRelid(heapRelation), reltuples, true);
- UpdateStats(RelationGetRelid(indexRelation), indtuples, false);
- if (oldPred != NULL)
+ * Since we just counted the tuples in the heap, we update its stats
+ * in pg_class to guarantee that the planner takes advantage of the
+ * index we just created. But, only update statistics during
+ * normal index definitions, not for indices on system catalogs
+ * created during bootstrap processing. We must close the relations
+ * before updating statistics to guarantee that the relcache entries
+ * are flushed when we increment the command counter in UpdateStats().
+ * But we do not release any locks on the relations; those will be
+ * held until end of transaction.
+ */
+ if (IsNormalProcessingMode())
{
- if (indtuples == reltuples)
- predicate = NULL;
- UpdateIndexPredicate(RelationGetRelid(indexRelation),
- oldPred, predicate);
+ Oid hrelid = RelationGetRelid(heapRelation);
+ Oid irelid = RelationGetRelid(indexRelation);
+
+ heap_close(heapRelation, NoLock);
+ index_close(indexRelation);
+ UpdateStats(hrelid, reltuples, true);
+ UpdateStats(irelid, indtuples, false);
+ if (oldPred != NULL)
+ {
+ if (indtuples == reltuples)
+ predicate = NULL;
+ UpdateIndexPredicate(irelid, oldPred, predicate);
+ }
}
}
Form_pg_index index;
bool isunique;
- pg_index = heap_openr(IndexRelationName);
+ pg_index = heap_openr(IndexRelationName, AccessShareLock);
ScanKeyEntryInitialize(&skey[0], (bits16) 0x0,
Anum_pg_index_indexrelid,
isunique = index->indisunique;
heap_endscan(scandesc);
- heap_close(pg_index);
+ heap_close(pg_index, AccessShareLock);
return isunique;
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
return false;
}
- pg_class = heap_openr(RelationRelationName);
+ pg_class = heap_openr(RelationRelationName, AccessShareLock);
htup = ClassOidIndexScan(pg_class, catId);
- heap_close(pg_class);
+ heap_close(pg_class, AccessShareLock);
if (!HeapTupleIsValid(htup))
{
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
else
nulls[Anum_pg_aggregate_agginitval2 - 1] = 'n';
- if (!RelationIsValid(aggdesc = heap_openr(AggregateRelationName)))
- elog(ERROR, "AggregateCreate: could not open '%s'",
- AggregateRelationName);
-
+ aggdesc = heap_openr(AggregateRelationName, RowExclusiveLock);
tupDesc = aggdesc->rd_att;
if (!HeapTupleIsValid(tup = heap_formtuple(tupDesc,
values,
elog(ERROR, "AggregateCreate: heap_formtuple failed");
if (!OidIsValid(heap_insert(aggdesc, tup)))
elog(ERROR, "AggregateCreate: heap_insert failed");
- heap_close(aggdesc);
-
+ heap_close(aggdesc, RowExclusiveLock);
}
char *
Assert(PointerIsValid(isNull));
Assert(xfuncno == 1 || xfuncno == 2);
+ /*
+ * since we will have to use fastgetattr (in case one or both init vals
+ * are NULL), we will need to open the relation. Do that first to
+ * ensure we don't get a stale tuple from the cache.
+ */
+
+ aggRel = heap_openr(AggregateRelationName, AccessShareLock);
+
tup = SearchSysCacheTuple(AGGNAME,
PointerGetDatum(aggName),
ObjectIdGetDatum(basetype),
initValAttno = Anum_pg_aggregate_agginitval1;
}
else
- /* can only be 1 or 2 */
{
+ /* can only be 1 or 2 */
transtype = ((Form_pg_aggregate) GETSTRUCT(tup))->aggtranstype2;
initValAttno = Anum_pg_aggregate_agginitval2;
}
- aggRel = heap_openr(AggregateRelationName);
- if (!RelationIsValid(aggRel))
- elog(ERROR, "AggNameGetInitVal: could not open \"%-.*s\"",
- AggregateRelationName);
-
- /*
- * must use fastgetattr in case one or other of the init values is
- * NULL
- */
textInitVal = (text *) fastgetattr(tup, initValAttno,
RelationGetDescr(aggRel),
isNull);
*isNull = true;
if (*isNull)
{
- heap_close(aggRel);
+ heap_close(aggRel, AccessShareLock);
return (char *) NULL;
}
strInitVal = textout(textInitVal);
- heap_close(aggRel);
+
+ heap_close(aggRel, AccessShareLock);
tup = SearchSysCacheTuple(TYPOID,
ObjectIdGetDatum(transtype),
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.41 1999/07/17 20:16:49 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.42 1999/09/18 19:06:33 tgl Exp $
*
* NOTES
* these routines moved here from commands/define.c and somewhat cleaned up.
* 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
* close the relation and return the operator oid.
* ----------------
*/
- heap_close(pg_operator_desc);
+ heap_close(pg_operator_desc, AccessShareLock);
return operatorObjectId;
}
* 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
* close the operator relation and return the oid.
* ----------------
*/
- heap_close(pg_operator_desc);
+ heap_close(pg_operator_desc, RowExclusiveLock);
return operatorObjectId;
}
/* last three fields were filled in above */
+ pg_operator_desc = heap_openr(OperatorRelationName, RowExclusiveLock);
+
/*
* If we are adding to an operator shell, get its t_self
*/
- pg_operator_desc = heap_openr(OperatorRelationName);
if (operatorObjectId)
{
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
nulls[i] = ' ';
}
- pg_operator_desc = heap_openr(OperatorRelationName);
+ pg_operator_desc = heap_openr(OperatorRelationName, RowExclusiveLock);
/* check and update the commutator, if necessary */
opKey[0].sk_argument = ObjectIdGetDatum(commId);
}
heap_endscan(pg_operator_scan);
- heap_close(pg_operator_desc);
+ heap_close(pg_operator_desc, RowExclusiveLock);
return;
}
heap_endscan(pg_operator_scan);
- heap_close(pg_operator_desc);
+ heap_close(pg_operator_desc, RowExclusiveLock);
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
values[i++] = (Datum) fmgr(F_TEXTIN, prosrc); /* prosrc */
values[i++] = (Datum) fmgr(F_TEXTIN, probin); /* probin */
- rel = heap_openr(ProcedureRelationName);
+ rel = heap_openr(ProcedureRelationName, RowExclusiveLock);
tupDesc = rel->rd_att;
tup = heap_formtuple(tupDesc,
CatalogIndexInsert(idescs, Num_pg_proc_indices, rel, tup);
CatalogCloseIndices(Num_pg_proc_indices, idescs);
}
- heap_close(rel);
+ heap_close(rel, RowExclusiveLock);
return tup->t_data->t_oid;
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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
* close the type relation and return the type oid.
* ----------------
*/
- heap_close(pg_type_desc);
+ heap_close(pg_type_desc, AccessShareLock);
return typeoid;
}
* open pg_type
* ----------------
*/
- pg_type_desc = heap_openr(TypeRelationName);
+ pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
/* ----------------
* insert the shell tuple
* close pg_type and return the tuple's oid.
* ----------------
*/
- heap_close(pg_type_desc);
+ heap_close(pg_type_desc, RowExclusiveLock);
return typoid;
}
* open pg_type and begin a scan for the type name.
* ----------------
*/
- pg_type_desc = heap_openr(TypeRelationName);
-
- /* -----------------
- * Set a write lock initially so as not upgrade a read to a write
- * when the heap_insert() or heap_replace() is called.
- * -----------------
- */
- LockRelation(pg_type_desc, AccessExclusiveLock);
+ pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
typeKey[0].sk_argument = PointerGetDatum(typeName);
pg_type_scan = heap_beginscan(pg_type_desc,
CatalogIndexInsert(idescs, Num_pg_type_indices, pg_type_desc, tup);
CatalogCloseIndices(Num_pg_type_indices, idescs);
}
- UnlockRelation(pg_type_desc, AccessExclusiveLock);
- heap_close(pg_type_desc);
+
+ heap_close(pg_type_desc, RowExclusiveLock);
return typeObjectId;
}
HeapTuple oldtup,
newtup;
- pg_type_desc = heap_openr(TypeRelationName);
+ pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
oldtup = SearchSysCacheTupleCopy(TYPNAME,
PointerGetDatum(oldTypeName),
if (!HeapTupleIsValid(oldtup))
{
- heap_close(pg_type_desc);
+ heap_close(pg_type_desc, RowExclusiveLock);
elog(ERROR, "TypeRename: type %s not defined", oldTypeName);
}
if (HeapTupleIsValid(newtup))
{
pfree(oldtup);
- heap_close(pg_type_desc);
+ heap_close(pg_type_desc, RowExclusiveLock);
elog(ERROR, "TypeRename: type %s already defined", newTypeName);
}
CatalogCloseIndices(Num_pg_type_indices, idescs);
pfree(oldtup);
- heap_close(pg_type_desc);
+ heap_close(pg_type_desc, RowExclusiveLock);
}
/*
* Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.53 1999/07/18 18:03:49 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.54 1999/09/18 19:06:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* transaction, since by assumption it is only called from outside any
* transaction.
*
- * Note that the system's use of pg_listener is confined to very short
- * intervals at the end of a transaction that contains NOTIFY statements,
- * or during the transaction caused by an inbound SIGUSR2. So the fact that
- * pg_listener is a global resource shouldn't cause too much performance
- * problem. But application authors ought to be discouraged from doing
- * LISTEN or UNLISTEN near the start of a long transaction --- that would
- * result in holding the pg_listener write lock for a long time, possibly
- * blocking unrelated activity. It could even lead to deadlock against another
- * transaction that touches the same user tables and then tries to NOTIFY.
- * Probably best to do LISTEN or UNLISTEN outside of transaction blocks.
+ * Although we grab AccessExclusiveLock on pg_listener for any operation,
+ * the lock is never held very long, so it shouldn't cause too much of
+ * a performance problem.
*
* An application that listens on the same relname it notifies will get
* NOTIFY messages for its own NOTIFYs. These can be ignored, if not useful,
TPRINTF(TRACE_NOTIFY, "Async_Notify: %s", relname);
- /*
- * We allocate list memory from the global malloc pool to ensure that
- * it will live until we want to use it. This is probably not
- * necessary any longer, since we will use it before the end of the
- * transaction. DLList only knows how to use malloc() anyway, but we
- * could probably palloc() the strings...
- */
if (!pendingNotifies)
pendingNotifies = DLNewList();
- notifyName = strdup(relname);
- DLAddHead(pendingNotifies, DLNewElem(notifyName));
-
- /*
- * NOTE: we could check to see if pendingNotifies already has an entry
- * for relname, and thus avoid making duplicate entries. However,
- * most apps probably don't notify the same name multiple times per
- * transaction, so we'd likely just be wasting cycles to make such a
- * check. AsyncExistsPendingNotify() doesn't really care whether the
- * list contains duplicates...
- */
+ /* no point in making duplicate entries in the list ... */
+ if (!AsyncExistsPendingNotify(relname))
+ {
+ /*
+ * We allocate list memory from the global malloc pool to ensure
+ * that it will live until we want to use it. This is probably not
+ * necessary any longer, since we will use it before the end of the
+ * transaction. DLList only knows how to use malloc() anyway, but we
+ * could probably palloc() the strings...
+ */
+ notifyName = strdup(relname);
+ DLAddHead(pendingNotifies, DLNewElem(notifyName));
+ }
}
/*
TPRINTF(TRACE_NOTIFY, "Async_Listen: %s", relname);
- lRel = heap_openr(ListenerRelationName);
- LockRelation(lRel, AccessExclusiveLock);
+ lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
tdesc = RelationGetDescr(lRel);
/* Detect whether we are already listening on this relname */
if (alreadyListener)
{
+ heap_close(lRel, AccessExclusiveLock);
elog(NOTICE, "Async_Listen: We are already listening on %s", relname);
- UnlockRelation(lRel, AccessExclusiveLock);
- heap_close(lRel);
return;
}
heap_insert(lRel, newtup);
pfree(newtup);
- UnlockRelation(lRel, AccessExclusiveLock);
- heap_close(lRel);
+ heap_close(lRel, AccessExclusiveLock);
/*
* now that we are listening, make sure we will unlisten before dying.
TPRINTF(TRACE_NOTIFY, "Async_Unlisten %s", relname);
+ lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
/* Note we assume there can be only one matching tuple. */
lTuple = SearchSysCacheTuple(LISTENREL, PointerGetDatum(relname),
Int32GetDatum(pid),
0, 0);
if (lTuple != NULL)
- {
- lRel = heap_openr(ListenerRelationName);
- LockRelation(lRel, AccessExclusiveLock);
heap_delete(lRel, &lTuple->t_self, NULL);
- UnlockRelation(lRel, AccessExclusiveLock);
- heap_close(lRel);
- }
+ heap_close(lRel, AccessExclusiveLock);
/*
* We do not complain about unlistening something not being listened;
TPRINTF(TRACE_NOTIFY, "Async_UnlistenAll");
- lRel = heap_openr(ListenerRelationName);
- LockRelation(lRel, AccessExclusiveLock);
+ lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
tdesc = RelationGetDescr(lRel);
/* Find and delete all entries with my listenerPID */
heap_delete(lRel, &lTuple->t_self, NULL);
heap_endscan(sRel);
- UnlockRelation(lRel, AccessExclusiveLock);
- heap_close(lRel);
+ heap_close(lRel, AccessExclusiveLock);
}
/*
TPRINTF(TRACE_NOTIFY, "AtCommit_Notify");
- lRel = heap_openr(ListenerRelationName);
- LockRelation(lRel, AccessExclusiveLock);
+ lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
tdesc = RelationGetDescr(lRel);
sRel = heap_beginscan(lRel, 0, SnapshotNow, 0, (ScanKey) NULL);
heap_endscan(sRel);
/*
- * We do not do RelationUnsetLockForWrite(lRel) here, because the
- * transaction is about to be committed anyway.
+ * We do NOT release the lock on pg_listener here; we need to hold it
+ * until end of transaction (which is about to happen, anyway) to
+ * ensure that notified backends see our tuple updates when they look.
+ * Else they might disregard the signal, which would make the
+ * application programmer very unhappy.
*/
- heap_close(lRel);
+ heap_close(lRel, NoLock);
ClearPendingNotifies();
StartTransactionCommand();
- lRel = heap_openr(ListenerRelationName);
- LockRelation(lRel, AccessExclusiveLock);
+ lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
tdesc = RelationGetDescr(lRel);
/* Scan only entries with my listenerPID */
heap_endscan(sRel);
/*
- * We do not do RelationUnsetLockForWrite(lRel) here, because the
- * transaction is about to be committed anyway.
+ * We do NOT release the lock on pg_listener here; we need to hold it
+ * until end of transaction (which is about to happen, anyway) to
+ * ensure that other backends see our tuple updates when they look.
+ * Otherwise, a transaction started after this one might mistakenly
+ * think it doesn't need to send this backend a new NOTIFY.
*/
- heap_close(lRel);
+ heap_close(lRel, NoLock);
CommitTransactionCommand();
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/*
* Like vacuum, cluster spans transactions, so I'm going to handle it
- * in the same way.
+ * in the same way: commit and restart transactions where needed.
+ *
+ * We grab exclusive access to the target rel and index for the
+ * duration of the initial transaction.
*/
- /* matches the StartTransaction in PostgresMain() */
-
- OldHeap = heap_openr(oldrelname);
- if (!RelationIsValid(OldHeap))
- {
- elog(ERROR, "cluster: unknown relation: \"%s\"",
- oldrelname);
- }
- OIDOldHeap = RelationGetRelid(OldHeap); /* Get OID for the index
- * scan */
+ OldHeap = heap_openr(oldrelname, AccessExclusiveLock);
+ OIDOldHeap = RelationGetRelid(OldHeap);
OldIndex = index_openr(oldindexname); /* Open old index relation */
- if (!RelationIsValid(OldIndex))
- {
- elog(ERROR, "cluster: unknown index: \"%s\"",
- oldindexname);
- }
- OIDOldIndex = RelationGetRelid(OldIndex); /* OID for the index scan */
+ LockRelation(OldIndex, AccessExclusiveLock);
+ OIDOldIndex = RelationGetRelid(OldIndex);
- heap_close(OldHeap);
+ heap_close(OldHeap, NoLock); /* do NOT give up the locks */
index_close(OldIndex);
/*
* will get the lock after being blocked and add rows which won't be
* present in the new table. Bleagh! I'd be best to try and ensure
* that no-one's in the tables for the entire duration of this process
- * with a pg_vlock.
+ * with a pg_vlock. XXX Isn't the above comment now invalid?
*/
NewHeap = copy_heap(OIDOldHeap);
OIDNewHeap = RelationGetRelid(NewHeap);
renamerel(NewIndexName, saveoldindexname);
/*
- * Again flush all the buffers.
+ * Again flush all the buffers. XXX perhaps not needed?
*/
CommitTransactionCommand();
StartTransactionCommand();
*/
snprintf(NewName, NAMEDATALEN, "temp_%x", OIDOldHeap);
- OldHeap = heap_open(OIDOldHeap);
+ OldHeap = heap_open(OIDOldHeap, AccessExclusiveLock);
OldHeapDesc = RelationGetDescr(OldHeap);
/*
if (!OidIsValid(OIDNewHeap))
elog(ERROR, "clusterheap: cannot create temporary heap relation\n");
- NewHeap = heap_open(OIDNewHeap);
+ /* XXX why are we bothering to do this: */
+ NewHeap = heap_open(OIDNewHeap, AccessExclusiveLock);
- heap_close(NewHeap);
- heap_close(OldHeap);
+ heap_close(NewHeap, AccessExclusiveLock);
+ heap_close(OldHeap, AccessExclusiveLock);
return NewHeap;
}
int natts;
FuncIndexInfo *finfo;
- NewHeap = heap_open(OIDNewHeap);
+ NewHeap = heap_open(OIDNewHeap, AccessExclusiveLock);
OldIndex = index_open(OIDOldIndex);
/*
Old_pg_index_Form->indisunique,
Old_pg_index_Form->indisprimary);
- heap_close(OldIndex);
- heap_close(NewHeap);
+ index_close(OldIndex);
+ heap_close(NewHeap, AccessExclusiveLock);
}
* Open the relations I need. Scan through the OldHeap on the OldIndex
* and insert each tuple into the NewHeap.
*/
- LocalNewHeap = (Relation) heap_open(OIDNewHeap);
- LocalOldHeap = (Relation) heap_open(OIDOldHeap);
+ LocalNewHeap = heap_open(OIDNewHeap, AccessExclusiveLock);
+ LocalOldHeap = heap_open(OIDOldHeap, AccessExclusiveLock);
LocalOldIndex = (Relation) index_open(OIDOldIndex);
ScanDesc = index_beginscan(LocalOldIndex, false, 0, (ScanKey) NULL);
index_endscan(ScanDesc);
index_close(LocalOldIndex);
- heap_close(LocalOldHeap);
- heap_close(LocalNewHeap);
+ heap_close(LocalOldHeap, AccessExclusiveLock);
+ heap_close(LocalNewHeap, AccessExclusiveLock);
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.53 1999/09/04 21:19:33 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.54 1999/09/18 19:06:40 tgl Exp $
*
* NOTES
* The PortalExecutorHeapMemory crap needs to be eliminated
{
Relation rel,
attrdesc;
+ Oid myrelid;
HeapTuple reltup;
HeapTuple attributeTuple;
Form_pg_attribute attribute;
relationName);
#endif
+ /*
+ * Grab an exclusive lock on the target table, which we will NOT release
+ * until end of transaction.
+ */
+ rel = heap_openr(relationName, AccessExclusiveLock);
+ myrelid = RelationGetRelid(rel);
+ heap_close(rel, NoLock); /* close rel but keep lock! */
+
/*
* we can't add a not null attribute
*/
{
if (inherits)
{
- Oid myrelid,
- childrelid;
+ Oid childrelid;
List *child,
*children;
- rel = heap_openr(relationName);
- if (!RelationIsValid(rel))
- {
- elog(ERROR, "PerformAddAttribute: unknown relation: \"%s\"",
- relationName);
- }
- myrelid = RelationGetRelid(rel);
- heap_close(rel);
-
/* this routine is actually in the planner */
children = find_all_inheritors(lconsi(myrelid, NIL), NIL);
childrelid = lfirsti(child);
if (childrelid == myrelid)
continue;
- rel = heap_open(childrelid);
- if (!RelationIsValid(rel))
- {
- elog(ERROR, "PerformAddAttribute: can't find catalog entry for inheriting class with oid %u",
- childrelid);
- }
+ rel = heap_open(childrelid, AccessExclusiveLock);
PerformAddAttribute((rel->rd_rel->relname).data,
userName, false, colDef);
- heap_close(rel);
+ heap_close(rel, AccessExclusiveLock);
}
}
}
- rel = heap_openr(RelationRelationName);
+ rel = heap_openr(RelationRelationName, RowExclusiveLock);
reltup = SearchSysCacheTupleCopy(RELNAME,
PointerGetDatum(relationName),
0, 0, 0);
if (!HeapTupleIsValid(reltup))
- {
- heap_close(rel);
elog(ERROR, "PerformAddAttribute: relation \"%s\" not found",
relationName);
- }
/*
* XXX is the following check sufficient?
{
elog(ERROR, "PerformAddAttribute: index relation \"%s\" not changed",
relationName);
- return;
}
minattnum = ((Form_pg_class) GETSTRUCT(reltup))->relnatts;
maxatts = minattnum + 1;
if (maxatts > MaxHeapAttributeNumber)
- {
- pfree(reltup);
- heap_close(rel);
elog(ERROR, "PerformAddAttribute: relations limited to %d attributes",
MaxHeapAttributeNumber);
- }
-
- attrdesc = heap_openr(AttributeRelationName);
- Assert(attrdesc);
- Assert(RelationGetForm(attrdesc));
+ attrdesc = heap_openr(AttributeRelationName, RowExclusiveLock);
/*
* Open all (if any) pg_attribute indices
0, 0);
if (HeapTupleIsValid(tup))
- {
- heap_close(attrdesc);
- heap_close(rel);
elog(ERROR, "PerformAddAttribute: attribute \"%s\" already exists in class \"%s\"",
colDef->colname, relationName);
- }
/*
* check to see if it is an array attribute.
if (hasindex)
CatalogCloseIndices(Num_pg_attr_indices, idescs);
- heap_close(attrdesc);
+
+ heap_close(attrdesc, RowExclusiveLock);
((Form_pg_class) GETSTRUCT(reltup))->relnatts = maxatts;
heap_replace(rel, &reltup->t_self, reltup, NULL);
CatalogCloseIndices(Num_pg_class_indices, ridescs);
pfree(reltup);
- heap_close(rel);
+ heap_close(rel, RowExclusiveLock);
}
void
Relation rel;
int aclresult;
- rel = heap_openr(lockstmt->relname);
- if (rel == NULL)
- elog(ERROR, "LOCK TABLE: relation %s can't be openned", lockstmt->relname);
+ rel = heap_openr(lockstmt->relname, NoLock);
+ if (! RelationIsValid(rel))
+ elog(ERROR, "Relation '%s' does not exist", lockstmt->relname);
if (lockstmt->mode == AccessShareLock)
aclresult = pg_aclcheck(lockstmt->relname, GetPgUserName(), ACL_RD);
LockRelation(rel, lockstmt->mode);
+ heap_close(rel, NoLock); /* close rel, keep lock */
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
Relation rel;
extern char *UserName; /* defined in global.c */
const AclMode required_access = from ? ACL_WR : ACL_RD;
+ LOCKMODE required_lock = from ? AccessExclusiveLock : AccessShareLock;
+ /* Note: AccessExclusive is probably overkill for copying to a relation,
+ * but that's what the existing code grabs on the rel's indices. If
+ * this is relaxed then I think the index locks need relaxed also.
+ */
int result;
- rel = heap_openr(relname);
- if (rel == NULL)
- elog(ERROR, "COPY command failed. Class %s "
- "does not exist.", relname);
+ rel = heap_openr(relname, required_lock);
result = pg_aclcheck(relname, UserName, required_access);
if (result != ACLCHECK_OK)
elog(ERROR, "%s: %s", relname, aclcheck_error_strings[result]);
- /* Above should not return */
- else if (!superuser() && !pipe)
+ else if (!pipe && !superuser())
elog(ERROR, "You must have Postgres superuser privilege to do a COPY "
"directly to or from a file. Anyone can COPY to stdout or "
"from stdin. Psql's \\copy command also works for anyone.");
- /* Above should not return. */
else
{
if (from)
pq_endcopyout(false);
}
}
+
+ heap_close(rel, required_lock);
}
pfree(elements);
pfree(typmod);
}
-
- heap_close(rel);
}
static void
pfree(typmod);
}
- /* comments in execUtils.c */
if (has_index)
{
for (i = 0; i < n_indices; i++)
{
if (index_rels[i] == NULL)
continue;
+ /* see comments in ExecOpenIndices() in execUtils.c */
if ((index_rels[i])->rd_rel->relam != BTREE_AM_OID &&
(index_rels[i])->rd_rel->relam != HASH_AM_OID)
UnlockRelation(index_rels[i], AccessExclusiveLock);
index_close(index_rels[i]);
}
}
- heap_close(rel);
}
/*
* Given the OID of a relation, return an array of index relation descriptors
* and the number of index relations. These relation descriptors are open
- * using heap_open().
+ * using index_open().
*
* Space for the array itself is palloc'ed.
*/
int i;
bool isnull;
- pg_index_rel = heap_openr(IndexRelationName);
+ pg_index_rel = heap_openr(IndexRelationName, AccessShareLock);
scandesc = heap_beginscan(pg_index_rel, 0, SnapshotNow, 0, NULL);
tupDesc = RelationGetDescr(pg_index_rel);
}
heap_endscan(scandesc);
- heap_close(pg_index_rel);
+ heap_close(pg_index_rel, AccessShareLock);
/* We cannot trust to relhasindex of the main_relation now, so... */
if (*n_indices == 0)
for (i = 0, scan = head; i < *n_indices; i++, scan = scan->next)
{
(*index_rels)[i] = index_open(scan->index_rel_oid);
- /* comments in execUtils.c */
+ /* see comments in ExecOpenIndices() in execUtils.c */
if ((*index_rels)[i] != NULL &&
((*index_rels)[i])->rd_rel->relam != BTREE_AM_OID &&
((*index_rels)[i])->rd_rel->relam != HASH_AM_OID)
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
*/
foreach(entry, schema)
{
- List *rest;
ColumnDef *coldef = lfirst(entry);
+ List *rest;
foreach(rest, lnext(entry))
{
-
/*
- * check for duplicated relation names
+ * check for duplicated names within the new relation
*/
ColumnDef *restdef = lfirst(rest);
TupleDesc tupleDesc;
TupleConstr *constr;
- relation = heap_openr(name);
- if (relation == NULL)
- {
- elog(ERROR,
- "MergeAttr: Can't inherit from non-existent superclass '%s'", name);
- }
- if (relation->rd_rel->relkind == 'S')
- elog(ERROR, "MergeAttr: Can't inherit from sequence superclass '%s'", name);
+ relation = heap_openr(name, AccessShareLock);
tupleDesc = RelationGetDescr(relation);
constr = tupleDesc->constr;
+ /* XXX shouldn't this test be stricter? No indexes, for example? */
+ if (relation->rd_rel->relkind == 'S')
+ elog(ERROR, "MergeAttr: Can't inherit from sequence superclass '%s'", name);
+
for (attrno = relation->rd_rel->relnatts - 1; attrno >= 0; attrno--)
{
Form_pg_attribute attribute = tupleDesc->attrs[attrno];
}
/*
- * 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
* Catalog INHERITS information.
* ----------------
*/
- relation = heap_openr(InheritsRelationName);
+ relation = heap_openr(InheritsRelationName, RowExclusiveLock);
desc = RelationGetDescr(relation);
seqNumber = 1;
seqNumber += 1;
}
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
/* ----------------
* Catalog IPL information.
* 3.
* ----------------
*/
- relation = heap_openr(InheritancePrecidenceListRelationName);
+ relation = heap_openr(InheritancePrecidenceListRelationName, RowExclusiveLock);
desc = RelationGetDescr(relation);
seqNumber = 1;
seqNumber += 1;
}
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
}
/*
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/* stop the vacuum daemon */
stop_vacuum(dbpath, dbname);
+ /* XXX what about stopping backends connected to the target database? */
+
path = ExpandDatabasePath(dbpath);
if (path == NULL)
elog(ERROR, "Unable to locate path '%s'"
utup = SearchSysCacheTuple(USENAME,
PointerGetDatum(userName),
0, 0, 0);
+ Assert(utup);
*userIdP = ((Form_pg_shadow) GETSTRUCT(utup))->usesysid;
use_super = ((Form_pg_shadow) GETSTRUCT(utup))->usesuper;
use_createdb = ((Form_pg_shadow) GETSTRUCT(utup))->usecreatedb;
/* Check to make sure database is owned by this user */
/*
- * need the reldesc to get the database owner out of dbtup and to set
- * a write lock on it.
+ * Acquire exclusive lock on pg_database from the beginning, even though
+ * we only need read access right here, to avoid potential deadlocks
+ * from upgrading our lock later. (Is this still necessary? Could we
+ * use something weaker than exclusive lock?)
*/
- dbrel = heap_openr(DatabaseRelationName);
-
- if (!RelationIsValid(dbrel))
- elog(FATAL, "%s: cannot open relation \"%-.*s\"",
- command, DatabaseRelationName);
+ dbrel = heap_openr(DatabaseRelationName, AccessExclusiveLock);
- /*
- * Acquire a write lock on pg_database from the beginning to avoid
- * upgrading a read lock to a write lock. Upgrading causes long
- * delays when multiple 'createdb's or 'destroydb's are run simult.
- * -mer 7/3/91
- */
- LockRelation(dbrel, AccessExclusiveLock);
dbtup = get_pg_dbtup(command, dbname, dbrel);
dbfound = HeapTupleIsValid(dbtup);
else
*dbIdP = InvalidOid;
- heap_close(dbrel);
+ /* We will keep the lock on dbrel until end of transaction. */
+ heap_close(dbrel, NoLock);
/*
* Now be sure that the user is allowed to do this.
*
* 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 $
*
*/
i = 0;
foreach(l, ((IndexScan *) plan)->indxid)
{
- relation = RelationIdCacheGetRelation((int) lfirst(l));
+ relation = RelationIdGetRelation(lfirsti(l));
+ Assert(relation);
if (++i > 1)
appendStringInfo(str, ", ");
appendStringInfo(str,
stringStringInfo((RelationGetRelationName(relation))->data));
+ /* drop relcache refcount from RelationIdGetRelation */
+ RelationDecrementReferenceCount(relation);
}
case T_SeqScan:
if (((Scan *) plan)->scanrelid > 0)
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
FIsetProcOid(funcInfo, tuple->t_data->t_oid);
}
- heapRelation = heap_open(relationId);
+ heapRelation = heap_open(relationId, ShareLock);
indexRelation = index_open(indexId);
- LockRelation(heapRelation, ShareLock);
-
InitIndexStrategy(numberOfAttributes, indexRelation, accessMethodId);
index_build(heapRelation, indexRelation, numberOfAttributes,
attributeNumberA, 0, NULL, funcInfo, predInfo);
+
+ /* heap and index rels are closed as a side-effect of index_build */
}
values[i++] = ObjectIdGetDatum(procTup->t_data->t_oid);
values[i++] = (Datum) fmgr(F_TEXTIN, stmt->plcompiler);
- rel = heap_openr(LanguageRelationName);
+ rel = heap_openr(LanguageRelationName, RowExclusiveLock);
tupDesc = rel->rd_att;
tup = heap_formtuple(tupDesc, values, nulls);
heap_insert(rel, tup);
- heap_close(rel);
- return;
+ heap_close(rel, RowExclusiveLock);
}
*/
case_translate_language_name(stmt->plname, languageName);
+ rel = heap_openr(LanguageRelationName, RowExclusiveLock);
+
langTup = SearchSysCacheTupleCopy(LANNAME,
PointerGetDatum(languageName),
0, 0, 0);
elog(ERROR, "Language %s doesn't exist", languageName);
if (!((Form_pg_language) GETSTRUCT(langTup))->lanispl)
- {
elog(ERROR, "Language %s isn't a created procedural language",
languageName);
- }
- rel = heap_openr(LanguageRelationName);
heap_delete(rel, &langTup->t_self, NULL);
pfree(langTup);
- heap_close(rel);
+ heap_close(rel, RowExclusiveLock);
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
else
oprtype = 'r';
+ relation = heap_openr(OperatorRelationName, RowExclusiveLock);
+
tup = SearchSysCacheTupleCopy(OPRNAME,
PointerGetDatum(operatorName),
ObjectIdGetDatum(typeId1),
ObjectIdGetDatum(typeId2),
CharGetDatum(oprtype));
- relation = heap_openr(OperatorRelationName);
if (HeapTupleIsValid(tup))
{
#ifndef NO_SECURITY
}
}
pfree(tup);
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
}
#ifdef NOTYET
ScanKeyEntryInitialize(&key[0],
0, 0, F_OIDEQ, (Datum) typeOid);
- rel = heap_openr(OperatorRelationName);
+ rel = heap_openr(OperatorRelationName, RowExclusiveLock);
for (i = 0; i < 3; ++i)
{
key[0].sk_attno = attnums[i];
heap_delete(rel, &tup->t_self, NULL);
heap_endscan(scan);
}
- heap_close(rel);
+ heap_close(rel, RowExclusiveLock);
}
/*
oidptr = (struct oidlist *) palloc(sizeof(*oidptr));
oidptr->next = NULL;
optr = oidptr;
- rel = heap_openr(AttributeRelationName);
+ rel = heap_openr(AttributeRelationName, AccessShareLock);
scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
{
}
optr->next = NULL;
heap_endscan(scan);
- heap_close(rel);
+ heap_close(rel, AccessShareLock);
+ optr = oidptr;
ScanKeyEntryInitialize(&key[0], 0,
ObjectIdAttributeNumber,
F_OIDEQ, (Datum) 0);
- optr = oidptr;
- rel = heap_openr(RelationRelationName);
+ /* get RowExclusiveLock because heap_destroy will need it */
+ rel = heap_openr(RelationRelationName, RowExclusiveLock);
while (PointerIsValid((char *) optr->next))
{
key[0].sk_argument = (Datum) (optr++)->reloid;
name = (((Form_pg_class) GETSTRUCT(tup))->relname).data;
heap_destroy_with_catalog(name);
}
+ heap_endscan(scan);
}
- heap_endscan(scan);
- heap_close(rel);
+ heap_close(rel, RowExclusiveLock);
}
#endif /* NOTYET */
typeName);
#endif
- relation = heap_openr(TypeRelationName);
+ relation = heap_openr(TypeRelationName, RowExclusiveLock);
+
tup = SearchSysCacheTuple(TYPNAME,
PointerGetDatum(typeName),
0, 0, 0);
-
if (!HeapTupleIsValid(tup))
{
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
elog(ERROR, "RemoveType: type '%s' does not exist", typeName);
}
- relation = heap_openr(TypeRelationName);
typeOid = tup->t_data->t_oid;
heap_delete(relation, &tup->t_self, NULL);
0, 0, 0);
if (!HeapTupleIsValid(tup))
{
- heap_close(relation);
- elog(ERROR, "RemoveType: type '%s' does not exist", typeName);
+ heap_close(relation, RowExclusiveLock);
+ elog(ERROR, "RemoveType: type '%s' does not exist", shadow_type);
}
- typeOid = tup->t_data->t_oid;
heap_delete(relation, &tup->t_self, NULL);
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
}
/*
}
#endif
- relation = heap_openr(ProcedureRelationName);
+ relation = heap_openr(ProcedureRelationName, RowExclusiveLock);
tup = SearchSysCacheTuple(PRONAME,
PointerGetDatum(functionName),
Int32GetDatum(nargs),
if (!HeapTupleIsValid(tup))
{
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
func_error("RemoveFunction", functionName, nargs, argList, NULL);
}
if ((((Form_pg_proc) GETSTRUCT(tup))->prolang) == INTERNALlanguageId)
{
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
elog(ERROR, "RemoveFunction: function \"%s\" is built-in", functionName);
}
heap_delete(relation, &tup->t_self, NULL);
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
}
void
}
#endif
- relation = heap_openr(AggregateRelationName);
+ relation = heap_openr(AggregateRelationName, RowExclusiveLock);
tup = SearchSysCacheTuple(AGGNAME,
PointerGetDatum(aggName),
ObjectIdGetDatum(basetypeID),
if (!HeapTupleIsValid(tup))
{
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
if (aggType)
{
elog(ERROR, "RemoveAggregate: aggregate '%s' for '%s' does not exist",
}
heap_delete(relation, &tup->t_self, NULL);
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
char *userName,
int recurse)
{
+ Relation targetrelation;
Relation attrelation;
HeapTuple reltup,
oldatttup,
relname);
#endif
+ /*
+ * Grab an exclusive lock on the target table, which we will NOT release
+ * until end of transaction.
+ */
+ targetrelation = heap_openr(relname, AccessExclusiveLock);
+ relid = RelationGetRelid(targetrelation);
+ heap_close(targetrelation, NoLock); /* close rel but keep lock! */
+
/*
* if the 'recurse' flag is set then we are supposed to rename this
* attribute in all classes that inherit from 'relname' (as well as in
*/
if (recurse)
{
- Oid myrelid,
- childrelid;
List *child,
*children;
- if ((myrelid = RelnameFindRelid(relname)) == InvalidOid)
- elog(ERROR, "renameatt: unknown relation: \"%s\"", relname);
-
/* this routine is actually in the planner */
- children = find_all_inheritors(lconsi(myrelid, NIL), NIL);
+ children = find_all_inheritors(lconsi(relid, NIL), NIL);
/*
* find_all_inheritors does the recursive search of the
*/
foreach(child, children)
{
+ Oid childrelid;
char childname[NAMEDATALEN];
childrelid = lfirsti(child);
- if (childrelid == myrelid)
+ if (childrelid == relid)
continue;
reltup = SearchSysCacheTuple(RELOID,
ObjectIdGetDatum(childrelid),
StrNCpy(childname,
((Form_pg_class) GETSTRUCT(reltup))->relname.data,
NAMEDATALEN);
- /* no more recursion! */
+ /* note we need not recurse again! */
renameatt(childname, oldattname, newattname, userName, 0);
}
}
-
- if ((relid = RelnameFindRelid(relname)) == InvalidOid)
- elog(ERROR, "renameatt: relation \"%s\" nonexistent", relname);
+ attrelation = heap_openr(AttributeRelationName, RowExclusiveLock);
oldatttup = SearchSysCacheTupleCopy(ATTNAME,
ObjectIdGetDatum(relid),
StrNCpy((((Form_pg_attribute) (GETSTRUCT(oldatttup)))->attname.data),
newattname, NAMEDATALEN);
- attrelation = heap_openr(AttributeRelationName);
heap_replace(attrelation, &oldatttup->t_self, oldatttup, NULL);
/* keep system catalog indices current */
CatalogCloseIndices(Num_pg_attr_indices, irelations);
pfree(oldatttup);
- heap_close(attrelation);
+ heap_close(attrelation, RowExclusiveLock);
}
/*
renamerel(char *oldrelname, char *newrelname)
{
int i;
+ Relation targetrelation;
Relation relrelation; /* for RELATION relation */
HeapTuple oldreltup;
char oldpath[MAXPGPATH],
elog(ERROR, "renamerel: Illegal class name: \"%s\" -- pg_ is reserved for system catalogs",
newrelname);
+ /*
+ * Grab an exclusive lock on the target table, which we will NOT release
+ * until end of transaction.
+ */
+ targetrelation = heap_openr(oldrelname, AccessExclusiveLock);
+ heap_close(targetrelation, NoLock); /* close rel but keep lock! */
+
+ relrelation = heap_openr(RelationRelationName, RowExclusiveLock);
+
oldreltup = SearchSysCacheTupleCopy(RELNAME,
PointerGetDatum(oldrelname),
0, 0, 0);
if (RelnameFindRelid(newrelname) != InvalidOid)
elog(ERROR, "renamerel: relation \"%s\" exists", newrelname);
+ /*
+ * XXX need to close relation and flush dirty buffers here!
+ */
+
/* rename the path first, so if this fails the rename's not done */
strcpy(oldpath, relpath(oldrelname));
strcpy(newpath, relpath(newrelname));
if (rename(oldpath, newpath) < 0)
elog(ERROR, "renamerel: unable to rename file: %s", oldpath);
+ /* rename additional segments of relation, too */
for (i = 1;; i++)
{
sprintf(toldpath, "%s.%d", oldpath, i);
newrelname, NAMEDATALEN);
/* insert fixed rel tuple */
- relrelation = heap_openr(RelationRelationName);
heap_replace(relrelation, &oldreltup->t_self, oldreltup, NULL);
/* keep the system catalog indices current */
CatalogIndexInsert(irelations, Num_pg_class_indices, relrelation, oldreltup);
CatalogCloseIndices(Num_pg_class_indices, irelations);
- heap_close(relrelation);
+ heap_close(relrelation, RowExclusiveLock);
}
DefineRelation(stmt, RELKIND_SEQUENCE);
- rel = heap_openr(seq->seqname);
- Assert(RelationIsValid(rel));
-
- LockRelation(rel, AccessExclusiveLock);
+ rel = heap_openr(seq->seqname, AccessExclusiveLock);
tupDesc = RelationGetDescr(rel);
if (WriteBuffer(buf) == STATUS_ERROR)
elog(ERROR, "DefineSequence: WriteBuffer failed");
- UnlockRelation(rel, AccessExclusiveLock);
- heap_close(rel);
-
- return;
-
+ heap_close(rel, AccessExclusiveLock);
}
temp = elm;
}
- temp->rel = heap_openr(name);
-
- if (!RelationIsValid(temp->rel))
- elog(ERROR, "%s.%s: sequence does not exist", name, caller);
-
- LockRelation(temp->rel, AccessShareLock);
+ temp->rel = heap_openr(name, AccessShareLock);
if (temp->rel->rd_rel->relkind != RELKIND_SEQUENCE)
elog(ERROR, "%s.%s: %s is not sequence !", name, caller, name);
}
return elm;
-
}
SeqTable elm;
Relation rel;
- for (elm = seqtab; elm != (SeqTable) NULL;)
+ for (elm = seqtab; elm != (SeqTable) NULL; elm = elm->next)
{
if (elm->rel != (Relation) NULL) /* opened in current xact */
{
rel = elm->rel;
elm->rel = (Relation) NULL;
- UnlockRelation(rel, AccessShareLock);
- heap_close(rel);
+ heap_close(rel, AccessShareLock);
}
- elm = elm->next;
}
-
- return;
-
}
elog(ERROR, "%s: %s", stmt->relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
#endif
- rel = heap_openr(stmt->relname);
- if (!RelationIsValid(rel))
- elog(ERROR, "CreateTrigger: there is no relation %s", stmt->relname);
-
- LockRelation(rel, AccessExclusiveLock);
+ rel = heap_openr(stmt->relname, AccessExclusiveLock);
TRIGGER_CLEAR_TYPE(tgtype);
if (stmt->before)
}
/* Scan pg_trigger */
- tgrel = heap_openr(TriggerRelationName);
- LockRelation(tgrel, AccessExclusiveLock);
+ tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
F_OIDEQ, RelationGetRelid(rel));
tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
CatalogIndexInsert(idescs, Num_pg_trigger_indices, tgrel, tuple);
CatalogCloseIndices(Num_pg_trigger_indices, idescs);
pfree(tuple);
- UnlockRelation(tgrel, AccessExclusiveLock);
- heap_close(tgrel);
+ heap_close(tgrel, RowExclusiveLock);
pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1]));
pfree(DatumGetPointer(values[Anum_pg_trigger_tgargs - 1]));
/* update pg_class */
+ pgrel = heap_openr(RelationRelationName, RowExclusiveLock);
tuple = SearchSysCacheTupleCopy(RELNAME,
PointerGetDatum(stmt->relname),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "CreateTrigger: relation %s not found in pg_class", stmt->relname);
- pgrel = heap_openr(RelationRelationName);
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1;
RelationInvalidateHeapTuple(pgrel, tuple);
heap_replace(pgrel, &tuple->t_self, tuple, NULL);
CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
CatalogCloseIndices(Num_pg_class_indices, ridescs);
pfree(tuple);
- heap_close(pgrel);
+ heap_close(pgrel, RowExclusiveLock);
CommandCounterIncrement();
oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
rel->rd_rel->reltriggers = found + 1;
RelationBuildTriggers(rel);
MemoryContextSwitchTo(oldcxt);
- heap_close(rel);
- return;
+ /* Keep lock on target rel until end of xact */
+ heap_close(rel, NoLock);
}
void
elog(ERROR, "%s: %s", stmt->relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
#endif
- rel = heap_openr(stmt->relname);
- if (!RelationIsValid(rel))
- elog(ERROR, "DropTrigger: there is no relation %s", stmt->relname);
+ rel = heap_openr(stmt->relname, AccessExclusiveLock);
- LockRelation(rel, AccessExclusiveLock);
-
- tgrel = heap_openr(TriggerRelationName);
- LockRelation(tgrel, AccessExclusiveLock);
+ tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
F_OIDEQ, RelationGetRelid(rel));
tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
elog(ERROR, "DropTrigger: there is no trigger %s on relation %s",
stmt->trigname, stmt->relname);
if (tgfound > 1)
- elog(NOTICE, "DropTrigger: found (and deleted) %d trigger %s on relation %s",
+ elog(NOTICE, "DropTrigger: found (and deleted) %d triggers %s on relation %s",
tgfound, stmt->trigname, stmt->relname);
heap_endscan(tgscan);
- UnlockRelation(tgrel, AccessExclusiveLock);
- heap_close(tgrel);
+ heap_close(tgrel, RowExclusiveLock);
+ /* update pg_class */
+ pgrel = heap_openr(RelationRelationName, RowExclusiveLock);
tuple = SearchSysCacheTupleCopy(RELNAME,
PointerGetDatum(stmt->relname),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "DropTrigger: relation %s not found in pg_class", stmt->relname);
- /* update pg_class */
- pgrel = heap_openr(RelationRelationName);
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found;
RelationInvalidateHeapTuple(pgrel, tuple);
heap_replace(pgrel, &tuple->t_self, tuple, NULL);
CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
CatalogCloseIndices(Num_pg_class_indices, ridescs);
pfree(tuple);
- heap_close(pgrel);
+ heap_close(pgrel, RowExclusiveLock);
CommandCounterIncrement();
oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
if (found > 0)
RelationBuildTriggers(rel);
MemoryContextSwitchTo(oldcxt);
- heap_close(rel);
- return;
+ /* Keep lock on target rel until end of xact */
+ heap_close(rel, NoLock);
}
void
ScanKeyData key;
HeapTuple tup;
- tgrel = heap_openr(TriggerRelationName);
- LockRelation(tgrel, AccessExclusiveLock);
+ tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
F_OIDEQ, RelationGetRelid(rel));
heap_delete(tgrel, &tup->t_self, NULL);
heap_endscan(tgscan);
- UnlockRelation(tgrel, AccessExclusiveLock);
- heap_close(tgrel);
-
+ heap_close(tgrel, RowExclusiveLock);
}
void
(RegProcedure) F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(relation)));
- tgrel = heap_openr(TriggerRelationName);
+ tgrel = heap_openr(TriggerRelationName, AccessShareLock);
irel = index_openr(TriggerRelidIndex);
sd = index_beginscan(irel, false, 1, &skey);
index_endscan(sd);
pfree(sd);
index_close(irel);
- heap_close(tgrel);
+ heap_close(tgrel, AccessShareLock);
/* Build trigdesc */
trigdesc->triggers = triggers;
*
* 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 $
*
*-------------------------------------------------------------------------
*/
*
* copy the modified contents of pg_shadow to a file used by the postmaster
* for user authentication. The file is stored as $PGDATA/pg_pwd.
+ *
+ * NB: caller is responsible for ensuring that only one backend can
+ * execute this routine at a time. Acquiring AccessExclusiveLock on
+ * pg_shadow is the standard way to do that.
*---------------------------------------------------------------------
*/
-static
-void
+static void
UpdatePgPwdFile(char *sql, CommandDest dest)
{
-
char *filename,
*tempname;
int bufsize;
/*
* Scan the pg_shadow relation to be certain the user doesn't already
- * exist.
+ * exist. Note we secure exclusive lock, because we also need to be
+ * sure of what the next usesysid should be, and we need to protect
+ * our update of the flat password file.
*/
- pg_shadow_rel = heap_openr(ShadowRelationName);
+ pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock);
pg_shadow_dsc = RelationGetDescr(pg_shadow_rel);
- /*
- * Secure a write lock on pg_shadow so we can be sure of what the next
- * usesysid should be.
- */
- LockRelation(pg_shadow_rel, AccessExclusiveLock);
-
scan = heap_beginscan(pg_shadow_rel, false, SnapshotNow, 0, NULL);
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
{
if (exists)
{
- UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
- heap_close(pg_shadow_rel);
+ heap_close(pg_shadow_rel, AccessExclusiveLock);
UserAbortTransactionBlock();
elog(ERROR,
"defineUser: user \"%s\" has already been created", stmt->user);
*
* XXX Ugly as this code is, it still fails to cope with ' or \ in any of
* the provided strings.
+ *
+ * XXX This routine would be *lots* better if it inserted the new
+ * tuple with formtuple/heap_insert. For one thing, all of the
+ * transaction-block gamesmanship could be eliminated, because
+ * it's only there to make the world safe for a recursive call
+ * to pg_exec_query_dest().
*/
snprintf(sql, SQL_LENGTH,
"insert into %s (usename,usesysid,usecreatedb,usetrace,"
pg_exec_query_dest(sql, dest, false);
/*
- * Add the stuff here for groups.
+ * Add stuff here for groups?
*/
+ /*
+ * Write the updated pg_shadow data to the flat password file.
+ * Because we are still holding AccessExclusiveLock on pg_shadow,
+ * we can be sure no other backend will try to write the flat
+ * file at the same time.
+ */
UpdatePgPwdFile(sql, dest);
/*
- * This goes after the UpdatePgPwdFile to be certain that two backends
- * to not attempt to write to the pg_pwd file at the same time.
+ * Now we can clean up.
*/
- UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
- heap_close(pg_shadow_rel);
+ heap_close(pg_shadow_rel, AccessExclusiveLock);
if (IsTransactionBlock() && !inblock)
EndTransactionBlock();
/*
* Scan the pg_shadow relation to be certain the user exists.
+ * Note we secure exclusive lock to protect our update of the
+ * flat password file.
*/
- pg_shadow_rel = heap_openr(ShadowRelationName);
+ pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock);
pg_shadow_dsc = RelationGetDescr(pg_shadow_rel);
- /*
- * Secure a write lock on pg_shadow so we can be sure that when the
- * dump of the pg_pwd file is done, there is not another backend doing
- * the same.
- */
- LockRelation(pg_shadow_rel, AccessExclusiveLock);
-
tuple = SearchSysCacheTuple(USENAME,
PointerGetDatum(stmt->user),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
{
- UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
- heap_close(pg_shadow_rel);
- UserAbortTransactionBlock(); /* needed? */
+ heap_close(pg_shadow_rel, AccessExclusiveLock);
+ UserAbortTransactionBlock();
elog(ERROR, "alterUser: user \"%s\" does not exist", stmt->user);
- return;
}
/*
* Create the update statement to modify the user.
+ *
+ * XXX see diatribe in preceding routine. This code is just as bogus.
*/
snprintf(sql, SQL_LENGTH, "update %s set", ShadowRelationName);
if (stmt->password)
- snprintf(sql, SQL_LENGTH, "%s passwd = '%s'", pstrdup(sql), stmt->password);
+ snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql),
+ " passwd = '%s'", stmt->password);
if (stmt->createdb)
{
- snprintf(sql, SQL_LENGTH, "%s %susecreatedb='%s'",
- pstrdup(sql), stmt->password ? "," : "",
+ snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql),
+ "%s usecreatedb='%s'",
+ stmt->password ? "," : "",
*stmt->createdb ? "t" : "f");
}
if (stmt->createuser)
{
- snprintf(sql, SQL_LENGTH, "%s %susesuper='%s'",
- pstrdup(sql), (stmt->password || stmt->createdb) ? "," : "",
+ snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql),
+ "%s usesuper='%s'",
+ (stmt->password || stmt->createdb) ? "," : "",
*stmt->createuser ? "t" : "f");
}
if (stmt->validUntil)
{
- snprintf(sql, SQL_LENGTH, "%s %svaluntil='%s'",
- pstrdup(sql),
+ snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql),
+ "%s valuntil='%s'",
(stmt->password || stmt->createdb || stmt->createuser) ? "," : "",
stmt->validUntil);
}
- snprintf(sql, SQL_LENGTH, "%s where usename = '%s'",
- pstrdup(sql), stmt->user);
+ snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql),
+ " where usename = '%s'",
+ stmt->user);
pg_exec_query_dest(sql, dest, false);
- /* do the pg_group stuff here */
+ /*
+ * Add stuff here for groups?
+ */
+ /*
+ * Write the updated pg_shadow data to the flat password file.
+ * Because we are still holding AccessExclusiveLock on pg_shadow,
+ * we can be sure no other backend will try to write the flat
+ * file at the same time.
+ */
UpdatePgPwdFile(sql, dest);
- UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
- heap_close(pg_shadow_rel);
+ /*
+ * Now we can clean up.
+ */
+ heap_close(pg_shadow_rel, AccessExclusiveLock);
if (IsTransactionBlock() && !inblock)
EndTransactionBlock();
extern void
RemoveUser(char *user, CommandDest dest)
{
-
char *pg_shadow;
Relation pg_shadow_rel,
pg_rel;
HeapScanDesc scan;
HeapTuple tuple;
Datum datum;
- char sql[512];
+ char sql[SQL_LENGTH];
bool n,
inblock;
int32 usesysid;
}
/*
- * Perform a scan of the pg_shadow relation to find the usesysid of
- * the user to be deleted. If it is not found, then return a warning
- * message.
+ * Scan the pg_shadow relation to find the usesysid of the user to be
+ * deleted. Note we secure exclusive lock, because we need to protect
+ * our update of the flat password file.
*/
- pg_shadow_rel = heap_openr(ShadowRelationName);
+ pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock);
pg_dsc = RelationGetDescr(pg_shadow_rel);
- /*
- * Secure a write lock on pg_shadow so we can be sure that when the
- * dump of the pg_pwd file is done, there is not another backend doing
- * the same.
- */
- LockRelation(pg_shadow_rel, AccessExclusiveLock);
-
tuple = SearchSysCacheTuple(USENAME,
PointerGetDatum(user),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
{
- UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
- heap_close(pg_shadow_rel);
+ heap_close(pg_shadow_rel, AccessExclusiveLock);
UserAbortTransactionBlock();
elog(ERROR, "removeUser: user \"%s\" does not exist", user);
}
* Perform a scan of the pg_database relation to find the databases
* owned by usesysid. Then drop them.
*/
- pg_rel = heap_openr(DatabaseRelationName);
+ pg_rel = heap_openr(DatabaseRelationName, AccessExclusiveLock);
pg_dsc = RelationGetDescr(pg_rel);
scan = heap_beginscan(pg_rel, false, SnapshotNow, 0, NULL);
if ((int) datum == usesysid)
{
datum = heap_getattr(tuple, Anum_pg_database_datname, pg_dsc, &n);
- if (memcmp((void *) datum, "template1", 9))
+ if (memcmp((void *) datum, "template1", 9) != 0)
{
dbase =
(char **) repalloc((void *) dbase, sizeof(char *) * (ndbase + 1));
}
}
heap_endscan(scan);
- heap_close(pg_rel);
+ heap_close(pg_rel, AccessExclusiveLock);
while (ndbase--)
{
elog(NOTICE, "Dropping database %s", dbase[ndbase]);
- snprintf(sql, SQL_LENGTH, "drop database %s", dbase[ndbase]);
+ snprintf(sql, SQL_LENGTH, "DROP DATABASE %s", dbase[ndbase]);
pfree((void *) dbase[ndbase]);
pg_exec_query_dest(sql, dest, false);
}
"delete from %s where usename = '%s'", ShadowRelationName, user);
pg_exec_query_dest(sql, dest, false);
+ /*
+ * Write the updated pg_shadow data to the flat password file.
+ * Because we are still holding AccessExclusiveLock on pg_shadow,
+ * we can be sure no other backend will try to write the flat
+ * file at the same time.
+ */
UpdatePgPwdFile(sql, dest);
- UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
- heap_close(pg_shadow_rel);
+ /*
+ * Now we can clean up.
+ */
+ heap_close(pg_shadow_rel, AccessExclusiveLock);
if (IsTransactionBlock() && !inblock)
EndTransactionBlock();
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
portalmem = PortalGetVariableMemory(vc_portal);
vrl = cur = (VRelList) NULL;
- rel = heap_openr(RelationRelationName);
+ rel = heap_openr(RelationRelationName, AccessShareLock);
tupdesc = RelationGetDescr(rel);
scan = heap_beginscan(rel, false, SnapshotNow, 1, &key);
if (found == false)
elog(NOTICE, "Vacuum: table not found");
-
heap_endscan(scan);
- heap_close(rel);
+ heap_close(rel, AccessShareLock);
CommitTransactionCommand();
return;
}
- /* now open the class and vacuum it */
- onerel = heap_open(relid);
+ /*
+ * Open the class, get an exclusive lock on it, and vacuum it
+ */
+ onerel = heap_open(relid, AccessExclusiveLock);
vacrelstats = (VRelStats *) palloc(sizeof(VRelStats));
vacrelstats->relid = relid;
vacrelstats->vacattrstats = (VacAttrStats *) NULL;
}
- /* we require the relation to be locked until the indices are cleaned */
- LockRelation(onerel, AccessExclusiveLock);
-
GetXmaxRecent(&XmaxRecent);
/* scan it */
pfree(fraged_pages.vpl_pagedesc);
}
- /* all done with this class */
- heap_close(onerel);
-
/* update statistics in pg_class */
vc_updstats(vacrelstats->relid, vacrelstats->num_pages,
vacrelstats->num_tuples, vacrelstats->hasindex, vacrelstats);
+ /* all done with this class, but hold lock until commit */
+ heap_close(onerel, NoLock);
+
/* next command frees attribute stats */
CommitTransactionCommand();
}
/*
* update number of tuples and number of pages in pg_class
*/
+ rd = heap_openr(RelationRelationName, RowExclusiveLock);
+
ctup = SearchSysCacheTupleCopy(RELOID,
ObjectIdGetDatum(relid),
0, 0, 0);
elog(ERROR, "pg_class entry for relid %u vanished during vacuuming",
relid);
- rd = heap_openr(RelationRelationName);
-
/* get the buffer cache tuple */
rtup.t_self = ctup->t_self;
heap_fetch(rd, SnapshotNow, &rtup, &buffer);
VacAttrStats *vacattrstats = vacrelstats->vacattrstats;
int natts = vacrelstats->va_natts;
- ad = heap_openr(AttributeRelationName);
- sd = heap_openr(StatisticRelationName);
+ ad = heap_openr(AttributeRelationName, RowExclusiveLock);
+ sd = heap_openr(StatisticRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&askey, 0, Anum_pg_attribute_attrelid,
F_INT4EQ, relid);
}
}
heap_endscan(scan);
- heap_close(ad);
- heap_close(sd);
+ heap_close(ad, RowExclusiveLock);
+ heap_close(sd, RowExclusiveLock);
}
/*
WriteBuffer(buffer);
- heap_close(rd);
+ heap_close(rd, RowExclusiveLock);
}
/*
HeapTuple tuple;
ScanKeyData key;
- pgstatistic = heap_openr(StatisticRelationName);
+ pgstatistic = heap_openr(StatisticRelationName, RowExclusiveLock);
if (relid != InvalidOid)
{
}
heap_endscan(scan);
- heap_close(pgstatistic);
+ heap_close(pgstatistic, RowExclusiveLock);
}
/*
ioid = (Oid *) palloc(10 * sizeof(Oid));
/* prepare a heap scan on the pg_index relation */
- pgindex = heap_openr(IndexRelationName);
+ pgindex = heap_openr(IndexRelationName, AccessShareLock);
tupdesc = RelationGetDescr(pgindex);
ScanKeyEntryInitialize(&key, 0x0, Anum_pg_index_indrelid,
}
heap_endscan(scan);
- heap_close(pgindex);
+ heap_close(pgindex, AccessShareLock);
if (i == 0)
{ /* No one index found */
/*-------------------------------------------------------------------------
*
* execAmi.c
- * miscellanious executor access method routines
+ * miscellaneous executor access method routines
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: execAmi.c,v 1.41 1999/07/17 20:16:56 momjian Exp $
+ * $Id: execAmi.c,v 1.42 1999/09/18 19:06:47 tgl Exp $
*
*-------------------------------------------------------------------------
*/
static Pointer ExecBeginScan(Relation relation, int nkeys, ScanKey skeys,
bool isindex, ScanDirection dir, Snapshot snapshot);
-static Relation ExecOpenR(Oid relationOid, bool isindex);
/* ----------------------------------------------------------------
* ExecOpenScanR
* abstraction someday -cim 9/9/89
* ----------------
*/
- relation = ExecOpenR(relOid, isindex);
- scanDesc = ExecBeginScan(relation,
- nkeys,
- skeys,
- isindex,
- dir,
- snapshot);
-
- if (returnRelation != NULL)
- *returnRelation = relation;
- if (scanDesc != NULL)
- *returnScanDesc = scanDesc;
-}
-
-/* ----------------------------------------------------------------
- * ExecOpenR
- *
- * returns a relation descriptor given an object id.
- * ----------------------------------------------------------------
- */
-static Relation
-ExecOpenR(Oid relationOid, bool isindex)
-{
- Relation relation;
-
- relation = (Relation) NULL;
/* ----------------
* open the relation with the correct call depending
* on whether this is a heap relation or an index relation.
+ *
+ * Do not lock the rel here; beginscan will acquire AccessShareLock.
* ----------------
*/
if (isindex)
- relation = index_open(relationOid);
+ relation = index_open(relOid);
else
- relation = heap_open(relationOid);
+ relation = heap_open(relOid, NoLock);
if (relation == NULL)
- elog(DEBUG, "ExecOpenR: relation == NULL, heap_open failed.");
+ elog(ERROR, "ExecOpenScanR: failed to open relation %u", relOid);
+
+ scanDesc = ExecBeginScan(relation,
+ nkeys,
+ skeys,
+ isindex,
+ dir,
+ snapshot);
- return relation;
+ if (returnRelation != NULL)
+ *returnRelation = relation;
+ if (scanDesc != NULL)
+ *returnScanDesc = scanDesc;
}
/* ----------------------------------------------------------------
if (scanDesc != NULL)
heap_endscan(scanDesc);
+ /*
+ * endscan released AccessShareLock acquired by beginscan. If we are
+ * holding any stronger locks on the rel, they should be held till end of
+ * xact. Therefore, we need only close the rel and not release locks.
+ */
if (relation != NULL)
- heap_close(relation);
+ heap_close(relation, NoLock);
/* ----------------
* if this is an index scan then we have to take care
* of the index relations as well..
* ----------------
*/
- if (nodeTag(node) == T_IndexScan)
+ if (IsA(node, IndexScan))
{
IndexScan *iscan = (IndexScan *) node;
IndexScanState *indexstate;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
resultRelationIndex = resultRelation;
rtentry = rt_fetch(resultRelationIndex, rangeTable);
resultRelationOid = rtentry->relid;
- resultRelationDesc = heap_open(resultRelationOid);
+ resultRelationDesc = heap_open(resultRelationOid, RowExclusiveLock);
if (resultRelationDesc->rd_rel->relkind == RELKIND_SEQUENCE)
elog(ERROR, "You can't change sequence relation %s",
resultRelationDesc->rd_rel->relname.data);
- LockRelation(resultRelationDesc, RowExclusiveLock);
-
resultRelationInfo = makeNode(RelationInfo);
resultRelationInfo->ri_RangeTableIndex = resultRelationIndex;
resultRelationInfo->ri_RelationDesc = resultRelationDesc;
{
rm = lfirst(l);
relid = ((RangeTblEntry *) nth(rm->rti - 1, rangeTable))->relid;
- relation = heap_open(relid);
- LockRelation(relation, RowShareLock);
+ relation = heap_open(relid, RowShareLock);
if (!(rm->info & ROW_MARK_FOR_UPDATE))
continue;
erm = (execRowMark *) palloc(sizeof(execRowMark));
*/
setheapoverride(true);
- intoRelationDesc = heap_open(intoRelationId);
+ intoRelationDesc = heap_open(intoRelationId,
+ AccessExclusiveLock);
setheapoverride(false);
}
}
/*
- * close the result relations if necessary
+ * close the result relations if necessary,
+ * but hold locks on them until xact commit
*/
if (resultRelationInfo != NULL)
{
Relation resultRelationDesc;
resultRelationDesc = resultRelationInfo->ri_RelationDesc;
- heap_close(resultRelationDesc);
+ heap_close(resultRelationDesc, NoLock);
/*
* close indices on the result relation
* close the "into" relation if necessary
*/
if (intoRelationDesc != NULL)
- heap_close(intoRelationDesc);
+ heap_close(intoRelationDesc, NoLock);
}
/* ----------------------------------------------------------------
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* open pg_index
* ----------------
*/
- indexRd = heap_openr(IndexRelationName);
+ indexRd = heap_openr(IndexRelationName, AccessShareLock);
/* ----------------
* form a scan key
* ----------------
*/
heap_endscan(indexSd);
- heap_close(indexRd);
+ heap_close(indexRd, AccessShareLock);
/* ----------------
* Now that we've collected the index information into three
/*
* Hack for not btree and hash indices: they use relation
- * level exclusive locking on updation (i.e. - they are
+ * level exclusive locking on update (i.e. - they are
* not ready for MVCC) and so we have to exclusively lock
* indices here to prevent deadlocks if we will scan them
* - index_beginscan places AccessShareLock, indices
continue;
/*
- * Notes in ExecOpenIndices.
+ * See notes in ExecOpenIndices.
*/
if (relationDescs[i]->rd_rel->relam != BTREE_AM_OID &&
relationDescs[i]->rd_rel->relam != HASH_AM_OID)
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
reloid = rtentry->relid;
rri = makeNode(RelationInfo);
rri->ri_RangeTableIndex = es_rri->ri_RangeTableIndex;
- rri->ri_RelationDesc = heap_open(reloid);
+ rri->ri_RelationDesc = heap_open(reloid, RowExclusiveLock);
rri->ri_NumIndices = 0;
rri->ri_IndexRelationDescs = NULL; /* index descs */
rri->ri_IndexRelationInfo = NULL; /* index key info */
resultRelationInfo = (RelationInfo *) lfirst(resultRelationInfoList);
resultRelationDesc = resultRelationInfo->ri_RelationDesc;
- heap_close(resultRelationDesc);
+ heap_close(resultRelationDesc, NoLock);
pfree(resultRelationInfo);
resultRelationInfoList = lnext(resultRelationInfoList);
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
F_OIDEQ,
ObjectIdGetDatum(pred_op));
- relation = heap_openr(AccessMethodOperatorRelationName);
+ relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock);
/*
* The following assumes that any given operator will only be in a
if (!HeapTupleIsValid(tuple))
{
elog(DEBUG, "clause_pred_clause_test: unknown pred_op");
+ heap_endscan(scan);
+ heap_close(relation, AccessShareLock);
return false;
}
aform = (Form_pg_amop) GETSTRUCT(tuple);
if (!HeapTupleIsValid(tuple))
{
elog(DEBUG, "clause_pred_clause_test: unknown clause_op");
+ heap_endscan(scan);
+ heap_close(relation, AccessShareLock);
return false;
}
aform = (Form_pg_amop) GETSTRUCT(tuple);
test_strategy = BT_implic_table[clause_strategy - 1][pred_strategy - 1];
if (test_strategy == 0)
+ {
+ heap_close(relation, AccessShareLock);
return false; /* the implication cannot be determined */
-
+ }
/*
* 4. From the same opclass, find the operator for the test strategy
if (!HeapTupleIsValid(tuple))
{
elog(DEBUG, "clause_pred_clause_test: unknown test_op");
+ heap_endscan(scan);
+ heap_close(relation, AccessShareLock);
return false;
}
aform = (Form_pg_amop) GETSTRUCT(tuple);
/* Get the test operator */
test_op = aform->amopopr;
+
heap_endscan(scan);
+ heap_close(relation, AccessShareLock);
/*
* 5. Evaluate the test
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
Resdom *resnode;
Relation reln;
Oid relid;
- Oid tletype;
int relnatts;
int i;
* declared return type, and be sure that attributes 1 .. n in the
* target list match the declared types.
*/
- reln = heap_open(typeTypeRelid(typ));
-
- if (!RelationIsValid(reln))
- elog(ERROR, "cannot open relation relid %u", typeTypeRelid(typ));
-
+ reln = heap_open(typeTypeRelid(typ), AccessShareLock);
relid = reln->rd_id;
relnatts = reln->rd_rel->relnatts;
{
TargetEntry *tle = lfirst(tlist);
Node *thenode = tle->expr;
+ Oid tletype = exprType(thenode);
- tlist = lnext(tlist);
- tletype = exprType(thenode);
-
-#ifdef NOT_USED /* fix me */
- /* this is tedious */
- if (IsA(thenode, Var))
- tletype = (Oid) ((Var *) thenode)->vartype;
- else if (IsA(thenode, Const))
- tletype = (Oid) ((Const *) thenode)->consttype;
- else if (IsA(thenode, Param))
- tletype = (Oid) ((Param *) thenode)->paramtype;
- else if (IsA(thenode, Expr))
- tletype = Expr;
-
- else if (IsA(thenode, LispList))
- {
- thenode = lfirst(thenode);
- if (IsA(thenode, Oper))
- tletype = (Oid) get_opresulttype((Oper *) thenode);
- else if (IsA(thenode, Func))
- tletype = (Oid) get_functype((Func *) thenode);
- else
- elog(ERROR, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ));
- }
- else
- elog(ERROR, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ));
-#endif
- /* reach right in there, why don't you? */
if (tletype != reln->rd_att->attrs[i - 1]->atttypid)
elog(ERROR, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ));
+ tlist = lnext(tlist);
}
- heap_close(reln);
-
- /* success */
- return;
+ heap_close(reln, AccessShareLock);
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/* Find an index on the given relation */
if (first)
{
- if (RelationIsValid(relation))
- heap_close(relation);
if (HeapScanIsValid(scan))
heap_endscan(scan);
+ scan = (HeapScanDesc) NULL;
+ if (RelationIsValid(relation))
+ heap_close(relation, AccessShareLock);
+ relation = (Relation) NULL;
ScanKeyEntryInitialize(&indexKey, 0,
Anum_pg_index_indrelid,
F_OIDEQ,
ObjectIdGetDatum(indrelid));
- relation = heap_openr(IndexRelationName);
+ relation = heap_openr(IndexRelationName, AccessShareLock);
scan = heap_beginscan(relation, 0, SnapshotNow,
1, &indexKey);
}
if (!HeapTupleIsValid(indexTuple))
{
heap_endscan(scan);
- heap_close(relation);
+ heap_close(relation, AccessShareLock);
scan = (HeapScanDesc) NULL;
relation = (Relation) NULL;
return 0;
info->relam = relam;
info->pages = indexRelation->rd_rel->relpages;
info->tuples = indexRelation->rd_rel->reltuples;
- heap_close(indexRelation);
+ index_close(indexRelation);
/*
* Find the index ordering keys
key[0].sk_nargs = key[0].sk_func.fn_nargs;
key[0].sk_argument = ObjectIdGetDatum((Oid) inhparent);
- relation = heap_openr(InheritsRelationName);
+ relation = heap_openr(InheritsRelationName, AccessShareLock);
scan = heap_beginscan(relation, 0, SnapshotNow, 1, key);
while (HeapTupleIsValid(inheritsTuple = heap_getnext(scan, 0)))
{
list = lappendi(list, inhrelid);
}
heap_endscan(scan);
- heap_close(relation);
+ heap_close(relation, AccessShareLock);
return list;
}
fmgr_info(F_OIDEQ, &key[0].sk_func);
key[0].sk_nargs = key[0].sk_func.fn_nargs;
- relation = heap_openr(VersionRelationName);
key[0].sk_argument = ObjectIdGetDatum(verrelid);
+ relation = heap_openr(VersionRelationName, AccessShareLock);
scan = heap_beginscan(relation, 0, SnapshotNow, 1, key);
while (HeapTupleIsValid(versionTuple = heap_getnext(scan, 0)))
{
heap_rescan(scan, 0, key);
}
heap_endscan(scan);
- heap_close(relation);
+ heap_close(relation, AccessShareLock);
return list;
}
*
* 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 $
*
*-------------------------------------------------------------------------
*/
parsetree = transformStmt(pstate, lfirst(pl));
if (pstate->p_target_relation != NULL)
- heap_close(pstate->p_target_relation);
+ heap_close(pstate->p_target_relation, AccessShareLock);
pstate->p_target_relation = NULL;
pstate->p_target_rangetblentry = NULL;
result = lappend(result,
transformStmt(pstate, lfirst(extras_before)));
if (pstate->p_target_relation != NULL)
- heap_close(pstate->p_target_relation);
+ heap_close(pstate->p_target_relation, AccessShareLock);
pstate->p_target_relation = NULL;
pstate->p_target_rangetblentry = NULL;
extras_before = lnext(extras_before);
result = lappend(result,
transformStmt(pstate, lfirst(extras_after)));
if (pstate->p_target_relation != NULL)
- heap_close(pstate->p_target_relation);
+ heap_close(pstate->p_target_relation, AccessShareLock);
pstate->p_target_relation = NULL;
pstate->p_target_rangetblentry = NULL;
extras_after = lnext(extras_after);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/* This could only happen for multi-action rules */
if (pstate->p_target_relation != NULL)
- heap_close(pstate->p_target_relation);
+ heap_close(pstate->p_target_relation, AccessShareLock);
pstate->p_target_rangetblentry = rte;
- pstate->p_target_relation = heap_open(rte->relid);
- /* will close relation later */
+ pstate->p_target_relation = heap_open(rte->relid, AccessShareLock);
+ /* will close relation later, see analyze.c */
}
/*
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
fmgr_info(F_NAMEEQ, (FmgrInfo *) &aggKey[0].sk_func);
aggKey[0].sk_argument = NameGetDatum(aggname);
- pg_aggregate_desc = heap_openr(AggregateRelationName);
+ pg_aggregate_desc = heap_openr(AggregateRelationName, AccessShareLock);
pg_aggregate_scan = heap_beginscan(pg_aggregate_desc,
0,
SnapshotSelf, /* ??? */
}
heap_endscan(pg_aggregate_scan);
- heap_close(pg_aggregate_desc);
+ heap_close(pg_aggregate_desc, AccessShareLock);
return ncandidates;
} /* agg_get_candidates() */
if (attisset)
{
toid = exprType(first_arg);
- rd = heap_openr(typeidTypeName(toid));
+ rd = heap_openr(typeidTypeName(toid), NoLock);
if (RelationIsValid(rd))
{
relname = RelationGetRelationName(rd)->data;
- heap_close(rd);
+ heap_close(rd, NoLock);
}
else
elog(ERROR, "Type '%s' is not a relation type",
CandidateList current_candidate;
int i;
- heapRelation = heap_openr(ProcedureRelationName);
+ heapRelation = heap_openr(ProcedureRelationName, AccessShareLock);
ScanKeyEntryInitialize(&skey,
(bits16) 0x0,
(AttrNumber) 1,
index_endscan(sd);
index_close(idesc);
- heap_close(heapRelation);
+ heap_close(heapRelation, AccessShareLock);
return candidates;
}
visited = DLNewList();
- inhrel = heap_openr(InheritsRelationName);
+ inhrel = heap_openr(InheritsRelationName, AccessShareLock);
inhtupdesc = RelationGetDescr(inhrel);
/*
if (qentry != (SuperQE *) NULL)
{
-
/* save the type id, rather than the relation id */
- if ((rd = heap_open(qentry->sqe_relid)) == (Relation) NULL)
+ rd = heap_open(qentry->sqe_relid, NoLock);
+ if (! RelationIsValid(rd))
elog(ERROR, "Relid %u does not exist", qentry->sqe_relid);
qentry->sqe_relid = typeTypeId(typenameType(RelationGetRelationName(rd)->data));
- heap_close(rd);
+ heap_close(rd, NoLock);
DLAddTail(visited, qe);
}
} while (qentry != (SuperQE *) NULL);
- heap_close(inhrel);
+ heap_close(inhrel, AccessShareLock);
if (nvisited > 0)
{
*/
/* add a tlist to the func node and return the Iter */
- rd = heap_openr(typeidTypeName(argtype));
+ rd = heap_openr(typeidTypeName(argtype), NoLock);
if (RelationIsValid(rd))
{
relid = RelationGetRelid(rd);
- heap_close(rd);
- }
- if (RelationIsValid(rd))
- {
func->func_tlist = setup_tlist(funcname, argrelid);
iter->itertype = attnumTypeId(rd, attnum);
+ heap_close(rd, NoLock);
return (Node *) iter;
}
else
{
/* add a tlist to the func node */
- rd = heap_openr(typeidTypeName(argtype));
- if (RelationIsValid(rd))
- {
- relid = RelationGetRelid(rd);
- heap_close(rd);
- }
+ rd = heap_openr(typeidTypeName(argtype), NoLock);
if (RelationIsValid(rd))
{
Expr *newexpr;
+ relid = RelationGetRelid(rd);
funcnode->func_tlist = setup_tlist(funcname, argrelid);
funcnode->functype = attnumTypeId(rd, attnum);
newexpr->oper = (Node *) funcnode;
newexpr->args = expr->args;
+ heap_close(rd, NoLock);
+
return (Node *) newexpr;
}
+ /* XXX why not an error condition if it's not there? */
}
* If the Param is a complex type, this could be a
* projection
*/
- rd = heap_openr(typeidTypeName(param->paramtype));
+ rd = heap_openr(typeidTypeName(param->paramtype), NoLock);
if (RelationIsValid(rd))
{
relid = RelationGetRelid(rd);
- heap_close(rd);
if ((attnum = get_attnum(relid, funcname))
!= InvalidAttrNumber)
{
param->paramtype = attnumTypeId(rd, attnum);
param->param_tlist = setup_tlist(funcname, relid);
+ heap_close(rd, NoLock);
return (Node *) param;
}
+ heap_close(rd, NoLock);
}
break;
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
HeapScanDesc pg_operator_scan;
HeapTuple tup;
Form_pg_operator oper;
- int nkeys;
int ncandidates = 0;
ScanKeyData opKey[3];
F_CHAREQ,
CharGetDatum('b'));
- nkeys = 2;
-
- pg_operator_desc = heap_openr(OperatorRelationName);
+ pg_operator_desc = heap_openr(OperatorRelationName, AccessShareLock);
pg_operator_scan = heap_beginscan(pg_operator_desc,
0,
SnapshotSelf, /* ??? */
- nkeys,
+ 2,
opKey);
while (HeapTupleIsValid(tup = heap_getnext(pg_operator_scan, 0)))
}
heap_endscan(pg_operator_scan);
- heap_close(pg_operator_desc);
+ heap_close(pg_operator_desc, AccessShareLock);
return ncandidates;
} /* binary_oper_get_candidates() */
fmgr_info(F_CHAREQ, (FmgrInfo *) &opKey[1].sk_func);
opKey[1].sk_argument = CharGetDatum(rightleft);
- pg_operator_desc = heap_openr(OperatorRelationName);
+ pg_operator_desc = heap_openr(OperatorRelationName, AccessShareLock);
pg_operator_scan = heap_beginscan(pg_operator_desc,
0,
SnapshotSelf, /* ??? */
}
heap_endscan(pg_operator_scan);
- heap_close(pg_operator_desc);
+ heap_close(pg_operator_desc, AccessShareLock);
return ncandidates;
} /* unary_oper_get_candidates() */
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
rte->relname = pstrdup(relname);
rte->refname = pstrdup(refname);
- relation = heap_openr(relname);
- if (relation == NULL)
- elog(ERROR, "%s: %s",
- relname, aclcheck_error_strings[ACLCHECK_NO_CLASS]);
-
+ relation = heap_openr(relname, AccessShareLock);
rte->relid = RelationGetRelid(relation);
-
- heap_close(relation);
+ heap_close(relation, AccessShareLock);
/*
* Flags - zero or more from inheritance,union,version or recursive
if (rte == NULL)
rte = addRangeTableEntry(pstate, relname, refname, FALSE, FALSE);
- rel = heap_open(rte->relid);
- if (rel == NULL)
- elog(ERROR, "Unable to expand all -- heap_open failed on %s",
- rte->refname);
+ rel = heap_open(rte->relid, AccessShareLock);
maxattrs = RelationGetNumberOfAttributes(rel);
te_list = lappend(te_list, te);
}
- heap_close(rel);
+ heap_close(rel, AccessShareLock);
return te_list;
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* Get the usename of the rules event relation owner
*/
rte = (RangeTblEntry *) nth(rt_index - 1, parsetree->rtable);
- ev_rel = heap_openr(rte->relname);
+ ev_rel = heap_openr(rte->relname, AccessShareLock);
usertup = SearchSysCacheTuple(USESYSID,
ObjectIdGetDatum(ev_rel->rd_rel->relowner),
0, 0, 0);
elog(ERROR, "cache lookup for userid %d failed",
ev_rel->rd_rel->relowner);
}
- heap_close(ev_rel);
+ heap_close(ev_rel, AccessShareLock);
evowner = nameout(&(((Form_pg_shadow) GETSTRUCT(usertup))->usename));
/*
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
extern void eval_as_new_xact();
char *template;
- eventrel = heap_openr(evobj);
- if (eventrel == NULL)
- elog(ERROR, "rules cannot be defined on relations not in schema");
+ eventrel = heap_openr(evobj, AccessShareLock);
eventrel_oid = RelationGetRelid(eventrel);
/*
evslot_index = -1;
else
evslot_index = attnameAttNum(eventrel, (char *) evslot);
- heap_close(eventrel);
+ heap_close(eventrel, AccessShareLock);
if (evinstead)
is_instead = "t";
* ... the targetlist of the SELECT action must exactly match the
* event relation, ...
*/
- event_relation = heap_openr(event_obj->relname);
- if (event_relation == NULL)
- elog(ERROR, "virtual relations not supported yet");
+ event_relation = heap_openr(event_obj->relname, AccessShareLock);
if (event_relation->rd_att->natts != length(query->targetList))
elog(ERROR, "select rules target list must match event relations structure");
}
}
- heap_close(event_relation);
+ heap_close(event_relation, AccessShareLock);
/*
* LIMIT in view is not supported
* This rule is allowed - install it.
*/
- event_relation = heap_openr(event_obj->relname);
- if (event_relation == NULL)
- elog(ERROR, "virtual relations not supported yet");
+ event_relation = heap_openr(event_obj->relname, AccessShareLock);
ev_relid = RelationGetRelid(event_relation);
if (eslot_string == NULL)
event_attno = attnameAttNum(event_relation, eslot_string);
event_attype = attnumTypeId(event_relation, event_attno);
}
- heap_close(event_relation);
+ heap_close(event_relation, AccessShareLock);
/* fix bug about instead nothing */
ValidateRule(event_type, event_obj->relname,
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
continue;
}
- rel = heap_openr(rte->relname);
+ rel = heap_openr(rte->relname, AccessShareLock);
if (rel->rd_rules == NULL)
{
- heap_close(rel);
+ heap_close(rel, AccessShareLock);
continue;
}
&modified);
}
- heap_close(rel);
+ heap_close(rel, AccessShareLock);
}
fireRIRonSubselect((Node *) parsetree);
* the statement is an update, insert or delete - fire rules on it.
*/
rt_entry = rt_fetch(result_relation, parsetree->rtable);
- rt_entry_relation = heap_openr(rt_entry->relname);
+ rt_entry_relation = heap_openr(rt_entry->relname, AccessShareLock);
rt_entry_locks = rt_entry_relation->rd_rules;
- heap_close(rt_entry_relation);
+ heap_close(rt_entry_relation, AccessShareLock);
if (rt_entry_locks != NULL)
{
}
return product_queries;
-
}
rte = (RangeTblEntry *) nth(parsetree->resultRelation - 1,
parsetree->rtable);
- rd = heap_openr(rte->relname);
+ rd = heap_openr(rte->relname, AccessShareLock);
foreach(tl, parsetree->targetList)
{
tle->resdom->resno = 0;
}
- heap_close(rd);
+ heap_close(rd, AccessShareLock);
}
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/*
* Open the pg_rewrite relation.
*/
- RewriteRelation = heap_openr(RewriteRelationName);
+ RewriteRelation = heap_openr(RewriteRelationName, RowExclusiveLock);
/*
* Scan the RuleRelation ('pg_rewrite') until we find a tuple
*/
if (!HeapTupleIsValid(tuple))
{
- heap_close(RewriteRelation);
+ heap_close(RewriteRelation, RowExclusiveLock);
elog(ERROR, "Rule '%s' not found\n", ruleName);
}
heap_delete(RewriteRelation, &tuple->t_self, NULL);
pfree(tuple);
- heap_close(RewriteRelation);
+ heap_close(RewriteRelation, RowExclusiveLock);
}
/*
/*
* 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
heap_delete(RewriteRelation, &tuple->t_self, NULL);
heap_endscan(scanDesc);
- heap_close(RewriteRelation);
+ heap_close(RewriteRelation, RowExclusiveLock);
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
char *rule_evqual_string = NULL;
Node *rule_evqual = NULL;
- ruleRelation = heap_openr(RewriteRelationName);
+ ruleRelation = heap_openr(RewriteRelationName, AccessShareLock);
ruleTupdesc = RelationGetDescr(ruleRelation);
ruletuple = SearchSysCacheTuple(RULOID,
ObjectIdGetDatum(ruleoid),
ruleparse = (Query *) stringToNode(ruleaction);
rule_evqual = (Node *) stringToNode(rule_evqual_string);
- heap_close(ruleRelation);
+ heap_close(ruleRelation, AccessShareLock);
*parseTrees = ruleparse;
return rule_evqual;
int
IsDefinedRewriteRule(char *ruleName)
{
- Relation RewriteRelation = NULL;
HeapTuple tuple;
-
- /*
- * Open the pg_rewrite relation.
- */
- RewriteRelation = heap_openr(RewriteRelationName);
-
tuple = SearchSysCacheTuple(REWRITENAME,
PointerGetDatum(ruleName),
0, 0, 0);
-
- /*
- * return whether or not the rewrite rule existed
- */
- heap_close(RewriteRelation);
return HeapTupleIsValid(tuple);
}
* pg_relation), find the appropriate tuple, and add the specified
* lock to it.
*/
+ relationRelation = heap_openr(RelationRelationName, RowExclusiveLock);
tuple = SearchSysCacheTupleCopy(RELOID,
ObjectIdGetDatum(relationId),
0, 0, 0);
Assert(HeapTupleIsValid(tuple));
- relationRelation = heap_openr(RelationRelationName);
((Form_pg_class) GETSTRUCT(tuple))->relhasrules = relhasrules;
heap_replace(relationRelation, &tuple->t_self, tuple, NULL);
CatalogCloseIndices(Num_pg_class_indices, idescs);
pfree(tuple);
- heap_close(relationRelation);
+ heap_close(relationRelation, RowExclusiveLock);
}
void
thisRule->actions = actions;
thisRule->isInstead = isInstead;
- relation = heap_open(relid);
+ relation = heap_open(relid, AccessShareLock);
/*
* modify or create a RuleLock cached by Relation
rulelock->numLocks++;
}
- heap_close(relation);
-
- return;
+ heap_close(relation, AccessShareLock);
}
void
int i;
MemoryContext oldcxt;
- relation = heap_open(relid);
+ relation = heap_open(relid, AccessShareLock);
rulelock = relation->rd_rules;
Assert(rulelock != NULL);
rulelock->numLocks--;
}
- heap_close(relation);
+ heap_close(relation, AccessShareLock);
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
{
if (!BufferIsLocal(buffer))
{
- LockRelId *lrelId = &(((LockInfo) (relation->lockInfo))->lockRelId);
+ LockRelId *lrelId = & relation->rd_lockInfo.lockRelId;
bufHdr = &BufferDescriptors[buffer - 1];
SpinAcquire(BufMgrLock);
status = smgrflush(DEFAULT_SMGR, bufrel, bufHdr->tag.blockNum,
(char *) MAKE_PTR(bufHdr->data));
+ /* drop relcache refcount incremented by RelationIdCacheGetRelation */
RelationDecrementReferenceCount(bufrel);
if (status == SM_FAIL)
elog(ERROR, "BufferSync: write error %u for %s",
bufHdr->tag.blockNum, bufHdr->sb_relname);
}
+ /* drop refcount from RelationIdCacheGetRelation */
if (reln != (Relation) NULL)
RelationDecrementReferenceCount(reln);
continue;
*/
if (!(bufHdr->flags & BM_JUST_DIRTIED))
bufHdr->flags &= ~BM_DIRTY;
+ /* drop refcount from RelationIdCacheGetRelation */
if (reln != (Relation) NULL)
RelationDecrementReferenceCount(reln);
}
/* XXX should be a critical section */
relid = BufferDescriptors[buffer - 1].tag.relId.relId;
relation = RelationIdGetRelation(relid);
+ Assert(relation);
+ /* drop relcache refcount incremented by RelationIdGetRelation */
RelationDecrementReferenceCount(relation);
if (RelationHasReferenceCountZero(relation))
{
/*
- * elog(NOTICE, "BufferGetRelation: 0->1");
+ * XXX why??
*/
RelationIncrementReferenceCount(relation);
}
else
{
-
/* blind write always flushes */
status = smgrblindwrt(DEFAULT_SMGR, bufHdr->sb_dbname,
bufHdr->sb_relname, bufdb, bufrel,
(char *) MAKE_PTR(bufHdr->data));
}
+ /* drop relcache refcount incremented by RelationIdCacheGetRelation */
if (reln != (Relation) NULL)
RelationDecrementReferenceCount(reln);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
smgrwrite(DEFAULT_SMGR, bufrel, bufHdr->tag.blockNum,
(char *) MAKE_PTR(bufHdr->data));
LocalBufferFlushCount++;
+
+ /* drop relcache refcount incremented by RelationIdCacheGetRelation */
RelationDecrementReferenceCount(bufrel);
}
smgrflush(DEFAULT_SMGR, bufrel, bufHdr->tag.blockNum,
(char *) MAKE_PTR(bufHdr->data));
LocalBufferFlushCount++;
+
+ /* drop relcache refcount incremented by RelationIdCacheGetRelation */
RelationDecrementReferenceCount(bufrel);
Assert(LocalRefCount[bufid] > 0);
smgrwrite(DEFAULT_SMGR, bufrel, buf->tag.blockNum,
(char *) MAKE_PTR(buf->data));
LocalBufferFlushCount++;
+
+ /* drop relcache refcount from RelationIdCacheGetRelation */
RelationDecrementReferenceCount(bufrel);
buf->tag.relId.relId = InvalidOid;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/* make the relation visible in this transaction */
CommandCounterIncrement();
- r = heap_openr(objname);
- if (!RelationIsValid(r))
- {
- elog(ERROR, "cannot create large object on %s under inversion",
- smgrout(DEFAULT_SMGR));
- }
+ /*--------------------
+ * We hold AccessShareLock on any large object we have open
+ * by inv_create or inv_open; it is released by inv_close.
+ * Note this will not conflict with ExclusiveLock or ShareLock
+ * that we acquire when actually reading/writing; it just prevents
+ * deletion of the large object while we have it open.
+ *--------------------
+ */
+ r = heap_openr(objname, AccessShareLock);
/*
* Now create a btree index on the relation's olastbyte attribute to
char *indname;
Relation indrel;
- r = heap_open(lobjId);
-
- if (!RelationIsValid(r))
- return (LargeObjectDesc *) NULL;
+ r = heap_open(lobjId, AccessShareLock);
indname = pstrdup((r->rd_rel->relname).data);
obj_desc->iscan = NULL;
}
- heap_close(obj_desc->heap_r);
index_close(obj_desc->index_r);
+ heap_close(obj_desc->heap_r, AccessShareLock);
pfree(obj_desc);
}
Relation r;
r = (Relation) RelationIdGetRelation(lobjId);
- if (!RelationIsValid(r) || r->rd_rel->relkind == RELKIND_INDEX)
+ if (!RelationIsValid(r) || r->rd_rel->relkind != RELKIND_LOBJECT)
return -1;
heap_destroy_with_catalog(r->rd_rel->relname.data);
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);
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.34 1999/09/04 18:42:14 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.35 1999/09/18 19:07:38 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
+
#include "access/transam.h"
#include "catalog/catalog.h"
+#include "miscadmin.h"
#include "utils/inval.h"
-extern Oid MyDatabaseId;
static LOCKMASK LockConflicts[] = {
(int) NULL,
/*
* RelationInitLockInfo
* Initializes the lock information in a relation descriptor.
+ *
+ * relcache.c must call this during creation of any reldesc.
*/
void
RelationInitLockInfo(Relation relation)
{
- LockInfo info;
char *relname;
- MemoryContext oldcxt;
- extern Oid MyDatabaseId; /* XXX use include */
- extern GlobalMemory CacheCxt;
Assert(RelationIsValid(relation));
Assert(OidIsValid(RelationGetRelid(relation)));
- info = (LockInfo) relation->lockInfo;
-
- if (LockInfoIsValid(info))
- return;
-
relname = (char *) RelationGetRelationName(relation);
- oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
- info = (LockInfo) palloc(sizeof(LockInfoData));
- MemoryContextSwitchTo(oldcxt);
+ relation->rd_lockInfo.lockRelId.relId = RelationGetRelid(relation);
- info->lockRelId.relId = RelationGetRelid(relation);
if (IsSharedSystemRelationName(relname))
- info->lockRelId.dbId = InvalidOid;
+ relation->rd_lockInfo.lockRelId.dbId = InvalidOid;
else
- info->lockRelId.dbId = MyDatabaseId;
-
- relation->lockInfo = (Pointer) info;
+ relation->rd_lockInfo.lockRelId.dbId = MyDatabaseId;
}
/*
void
LockRelation(Relation relation, LOCKMODE lockmode)
{
- LockInfo lockinfo;
LOCKTAG tag;
if (LockingDisabled())
return;
- if (!LockInfoIsValid(relation->lockInfo))
- RelationInitLockInfo(relation);
-
- lockinfo = (LockInfo) relation->lockInfo;
-
MemSet(&tag, 0, sizeof(tag));
- tag.relId = lockinfo->lockRelId.relId;
- tag.dbId = lockinfo->lockRelId.dbId;
+ tag.relId = relation->rd_lockInfo.lockRelId.relId;
+ tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
tag.objId.blkno = InvalidBlockNumber;
LockAcquire(LockTableId, &tag, lockmode);
void
UnlockRelation(Relation relation, LOCKMODE lockmode)
{
- LockInfo lockinfo;
LOCKTAG tag;
if (LockingDisabled())
return;
- lockinfo = (LockInfo) relation->lockInfo;
-
- if (!LockInfoIsValid(lockinfo))
- {
- elog(ERROR,
- "Releasing a lock on %s with invalid lock information",
- RelationGetRelationName(relation));
- }
-
MemSet(&tag, 0, sizeof(tag));
- tag.relId = lockinfo->lockRelId.relId;
- tag.dbId = lockinfo->lockRelId.dbId;
+ tag.relId = relation->rd_lockInfo.lockRelId.relId;
+ tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
tag.objId.blkno = InvalidBlockNumber;
LockRelease(LockTableId, &tag, lockmode);
- return;
}
/*
void
LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
{
- LockInfo lockinfo;
LOCKTAG tag;
if (LockingDisabled())
return;
- if (!LockInfoIsValid(relation->lockInfo))
- RelationInitLockInfo(relation);
-
- lockinfo = (LockInfo) relation->lockInfo;
-
MemSet(&tag, 0, sizeof(tag));
- tag.relId = lockinfo->lockRelId.relId;
- tag.dbId = lockinfo->lockRelId.dbId;
+ tag.relId = relation->rd_lockInfo.lockRelId.relId;
+ tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
tag.objId.blkno = blkno;
LockAcquire(LockTableId, &tag, lockmode);
- return;
}
/*
void
UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
{
- LockInfo lockinfo;
LOCKTAG tag;
if (LockingDisabled())
return;
- lockinfo = (LockInfo) relation->lockInfo;
-
- if (!LockInfoIsValid(lockinfo))
- {
- elog(ERROR,
- "Releasing a lock on %s with invalid lock information",
- RelationGetRelationName(relation));
- }
-
MemSet(&tag, 0, sizeof(tag));
- tag.relId = lockinfo->lockRelId.relId;
- tag.dbId = lockinfo->lockRelId.dbId;
+ tag.relId = relation->rd_lockInfo.lockRelId.relId;
+ tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
tag.objId.blkno = blkno;
LockRelease(LockTableId, &tag, lockmode);
- return;
}
void
tag.objId.xid = xid;
LockAcquire(LockTableId, &tag, ExclusiveLock);
- return;
}
void
tag.objId.xid = xid;
LockRelease(LockTableId, &tag, ExclusiveLock);
- return;
}
void
*/
if (!TransactionIdDidCommit(xid) && !TransactionIdDidAbort(xid))
TransactionIdAbort(xid);
-
- return;
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.61 1999/07/17 20:17:46 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.62 1999/09/18 19:07:38 tgl Exp $
*
* NOTES
* Outside modules can create a lock table and acquire/release
if (!result)
{
elog(NOTICE, "LockAcquire: xid table corrupted");
- return STATUS_ERROR;
+ return FALSE;
}
/*
TPRINTF(TRACE_USERLOCKS, "LockRelease: no lock with this tag");
else
#endif
- elog(NOTICE, "LockReplace: xid table corrupted");
+ elog(NOTICE, "LockRelease: xid table corrupted");
return FALSE;
}
XID_PRINT("LockRelease: found", result);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
case T_DestroyStmt:
{
DestroyStmt *stmt = (DestroyStmt *) parsetree;
- List *arg;
List *args = stmt->relNames;
- Relation rel;
+ List *arg;
PS_SET_STATUS(commandTag = "DROP");
CHECK_IF_ABORTED();
+ /* check as much as we can before we start dropping ... */
foreach(arg, args)
{
+ Relation rel;
+
relname = strVal(lfirst(arg));
if (!allowSystemTableMods && IsSystemRelationName(relname))
elog(ERROR, "class \"%s\" is a system catalog",
relname);
- rel = heap_openr(relname);
- if (RelationIsValid(rel))
- {
- if (stmt->sequence &&
- rel->rd_rel->relkind != RELKIND_SEQUENCE)
- elog(ERROR, "Use DROP TABLE to drop table '%s'",
- relname);
- if (!(stmt->sequence) &&
- rel->rd_rel->relkind == RELKIND_SEQUENCE)
- elog(ERROR, "Use DROP SEQUENCE to drop sequence '%s'",
- relname);
- heap_close(rel);
- }
+ rel = heap_openr(relname, AccessExclusiveLock);
+ if (stmt->sequence &&
+ rel->rd_rel->relkind != RELKIND_SEQUENCE)
+ elog(ERROR, "Use DROP TABLE to drop table '%s'",
+ relname);
+ if (!(stmt->sequence) &&
+ rel->rd_rel->relkind == RELKIND_SEQUENCE)
+ elog(ERROR, "Use DROP SEQUENCE to drop sequence '%s'",
+ relname);
+ /* close rel, but keep lock until end of xact */
+ heap_close(rel, NoLock);
#ifndef NO_SECURITY
if (!pg_ownercheck(userName, relname, RELNAME))
elog(ERROR, "you do not own class \"%s\"",
relname);
#endif
}
+ /* OK, terminate 'em all */
foreach(arg, args)
{
relname = strVal(lfirst(arg));
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/* Open the relation and get a relation descriptor */
- relation_to_scan = heap_openr(relation);
- if (!RelationIsValid(relation_to_scan))
- {
- elog(ERROR, "int4notin: unknown relation %s",
- relation);
- }
+ relation_to_scan = heap_openr(relation, AccessShareLock);
/* Find the column to search */
}
/* close the relation */
- heap_close(relation_to_scan);
+ heap_endscan(scan_descriptor);
+ heap_close(relation_to_scan, AccessShareLock);
+
return retval;
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
(RegProcedure) F_NAMEEQ,
PointerGetDatum(pro_name_or_oid));
- hdesc = heap_openr(ProcedureRelationName);
+ hdesc = heap_openr(ProcedureRelationName, AccessShareLock);
idesc = index_openr(ProcedureNameIndex);
sd = index_beginscan(idesc, false, 1, skey);
index_endscan(sd);
pfree(sd);
index_close(idesc);
+ heap_close(hdesc, AccessShareLock);
if (matches > 1)
elog(ERROR, "There is more than one procedure named %s.\n\tSupply the pg_proc oid inside single quotes.", pro_name_or_oid);
ScanKeyData key;
bool isnull;
- proc = heap_openr(ProcedureRelationName);
- if (!RelationIsValid(proc))
- {
- elog(ERROR, "regprocin: could not open %s",
- ProcedureRelationName);
- return 0;
- }
+ proc = heap_openr(ProcedureRelationName, AccessShareLock);
ScanKeyEntryInitialize(&key,
(bits16) 0,
(AttrNumber) 1,
procscan = heap_beginscan(proc, 0, SnapshotNow, 1, &key);
if (!HeapScanIsValid(procscan))
{
- heap_close(proc);
- elog(ERROR, "regprocin: could not being scan of %s",
+ heap_close(proc, AccessShareLock);
+ elog(ERROR, "regprocin: could not begin scan of %s",
ProcedureRelationName);
return 0;
}
result = (RegProcedure) 0;
heap_endscan(procscan);
- heap_close(proc);
+ heap_close(proc, AccessShareLock);
}
return (int32) result;
HeapScanDesc procscan;
ScanKeyData key;
- proc = heap_openr(ProcedureRelationName);
- if (!RelationIsValid(proc))
- {
- elog(ERROR, "regprocout: could not open %s", ProcedureRelationName);
- return 0;
- }
+ proc = heap_openr(ProcedureRelationName, AccessShareLock);
ScanKeyEntryInitialize(&key,
(bits16) 0,
(AttrNumber) ObjectIdAttributeNumber,
procscan = heap_beginscan(proc, 0, SnapshotNow, 1, &key);
if (!HeapScanIsValid(procscan))
{
- heap_close(proc);
- elog(ERROR, "regprocout: could not being scan of %s",
+ heap_close(proc, AccessShareLock);
+ elog(ERROR, "regprocout: could not begin scan of %s",
ProcedureRelationName);
return 0;
}
result[1] = '\0';
}
heap_endscan(procscan);
- heap_close(proc);
- return result;
+ heap_close(proc, AccessShareLock);
}
return result;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
HeapTuple typeTuple;
FmgrInfo inputproc;
- rel = heap_openr(StatisticRelationName);
+ rel = heap_openr(StatisticRelationName, AccessShareLock);
key[0].sk_argument = ObjectIdGetDatum(relid);
key[1].sk_argument = Int16GetDatum((int16) attnum);
{
/* no such stats entry */
heap_endscan(scan);
- heap_close(rel);
+ heap_close(rel, AccessShareLock);
return false;
}
}
heap_endscan(scan);
- heap_close(rel);
+ heap_close(rel, AccessShareLock);
return true;
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
replNull[i] = ' ';
/* change the pg_proc tuple */
- procrel = heap_openr(ProcedureRelationName);
- LockRelation(procrel, AccessExclusiveLock);
+ procrel = heap_openr(ProcedureRelationName, RowExclusiveLock);
tup = SearchSysCacheTuple(PROOID,
ObjectIdGetDatum(setoid),
CatalogIndexInsert(idescs, Num_pg_proc_indices, procrel, newtup);
CatalogCloseIndices(Num_pg_proc_indices, idescs);
}
- UnlockRelation(procrel, AccessExclusiveLock);
- heap_close(procrel);
+ heap_close(procrel, RowExclusiveLock);
}
return setoid;
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/* ----------------
* If no relation was passed we must open it to get access to
* its fields. If one of the other caches has already opened
- * it we use heap_open() instead of heap_openr()
+ * it we use heap_open() instead of heap_openr().
+ * XXX is that really worth the trouble of checking?
* ----------------
*/
if (!RelationIsValid(relation))
* ----------------
*/
if (cp)
- relation = heap_open(cp->relationId);
+ relation = heap_open(cp->relationId, NoLock);
else
- relation = heap_openr(cache->cc_relname);
+ relation = heap_openr(cache->cc_relname, NoLock);
didopen = 1;
}
* ----------------
*/
if (didopen)
- heap_close(relation);
+ heap_close(relation, NoLock);
/* ----------------
* initialize index information for the cache. this
DLMoveToFront(elt);
#ifdef CACHEDEBUG
- relation = heap_open(cache->relationId);
+ relation = heap_open(cache->relationId, NoLock);
CACHE3_elog(DEBUG, "SearchSysCache(%s): found in bucket %d",
RelationGetRelationName(relation), hash);
- heap_close(relation);
+ heap_close(relation, NoLock);
#endif /* CACHEDEBUG */
return ct->ct_tup;
* open the relation associated with the cache
* ----------------
*/
- relation = heap_open(cache->relationId);
+ relation = heap_open(cache->relationId, AccessShareLock);
CACHE2_elog(DEBUG, "SearchSysCache(%s)",
RelationGetRelationName(relation));
* and return the tuple we found (or NULL)
* ----------------
*/
- heap_close(relation);
+ heap_close(relation, AccessShareLock);
MemoryContextSwitchTo(oldcxt);
return ntp;
(*function) (ccp->id,
CatalogCacheComputeTupleHashIndex(ccp, relation, tuple),
&tuple->t_self);
-
- heap_close(relation);
}
/* ----------------
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* open pg_class and fetch a tuple
* ----------------
*/
- pg_class_desc = heap_openr(RelationRelationName);
+ pg_class_desc = heap_openr(RelationRelationName, AccessShareLock);
pg_class_scan = heap_beginscan(pg_class_desc, 0, SnapshotNow, 1, &key);
pg_class_tuple = heap_getnext(pg_class_scan, 0);
/* all done */
heap_endscan(pg_class_scan);
- heap_close(pg_class_desc);
+ heap_close(pg_class_desc, AccessShareLock);
return return_tuple;
}
Relation pg_class_desc;
HeapTuple return_tuple;
- pg_class_desc = heap_openr(RelationRelationName);
- if (!IsInitProcessingMode())
- LockRelation(pg_class_desc, AccessShareLock);
+ pg_class_desc = heap_openr(RelationRelationName, AccessShareLock);
switch (buildinfo.infotype)
{
default:
elog(ERROR, "ScanPgRelation: bad buildinfo");
-
- /*
- * XXX I hope this is right. It seems better than returning
- * an uninitialized value
- */
- return_tuple = NULL;
+ return_tuple = NULL; /* keep compiler quiet */
}
- /* all done */
- if (!IsInitProcessingMode())
- UnlockRelation(pg_class_desc, AccessShareLock);
- heap_close(pg_class_desc);
+ heap_close(pg_class_desc, AccessShareLock);
return return_tuple;
}
* 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);
/* ----------------
* ----------------
*/
heap_endscan(pg_attribute_scan);
- heap_close(pg_attribute_desc);
+ heap_close(pg_attribute_desc, AccessShareLock);
}
static void
constr->has_not_null = false;
- attrel = heap_openr(AttributeRelationName);
+ attrel = heap_openr(AttributeRelationName, AccessShareLock);
for (i = 1; i <= relation->rd_rel->relnatts; i++)
{
}
}
- heap_close(attrel);
+ heap_close(attrel, AccessShareLock);
if (constr->has_not_null || ndef > 0 || relation->rd_rel->relchecks)
{
* open pg_attribute and begin a scan
* ----------------
*/
- pg_rewrite_desc = heap_openr(RewriteRelationName);
+ pg_rewrite_desc = heap_openr(RewriteRelationName, AccessShareLock);
pg_rewrite_scan = heap_beginscan(pg_rewrite_desc, 0, SnapshotNow, 1, &key);
pg_rewrite_tupdesc = RelationGetDescr(pg_rewrite_desc);
* ----------------
*/
heap_endscan(pg_rewrite_scan);
- heap_close(pg_rewrite_desc);
+ heap_close(pg_rewrite_desc, AccessShareLock);
/* ----------------
* form a RuleLock and insert into relation
* uint16 rd_refcnt; reference count
* Form_pg_am rd_am; AM tuple
* Form_pg_class rd_rel; RELATION tuple
- * Oid rd_id; relations's object id
- * Pointer lockInfo; ptr. to misc. info.
- * TupleDesc rd_att; tuple desciptor
+ * Oid rd_id; relation's object id
+ * LockInfoData rd_lockInfo; lock manager's info
+ * TupleDesc rd_att; tuple descriptor
*
* Note: rd_ismem (rel is in-memory only) is currently unused
* by any part of the system. someday this will indicate that
*/
RelationGetRelid(relation) = relation->rd_att->attrs[0]->attrelid;
+ /* ----------------
+ * initialize the relation lock manager information
+ * ----------------
+ */
+ RelationInitLockInfo(relation); /* see lmgr.c */
+
/* ----------------
* add new reldesc to relcache
* ----------------
*/
RelationCacheInsert(relation);
- RelationInitLockInfo(relation);
-
/*
* Determining this requires a scan on pg_class, but to do the scan
* the rdesc for pg_class must already exist. Therefore we must do
/* --------------------------------
* RelationIdCacheGetRelation
*
- * only try to get the reldesc by looking up the cache
- * do not go to the disk. this is used by BlockPrepareFile()
- * and RelationIdGetRelation below.
+ * Lookup a reldesc by OID.
+ * Only try to get the reldesc by looking up the cache
+ * do not go to the disk.
+ *
+ * NB: relation ref count is incremented if successful.
+ * Caller should eventually decrement count. (Usually,
+ * that happens by calling RelationClose().)
* --------------------------------
*/
Relation
/* --------------------------------
* RelationNameCacheGetRelation
+ *
+ * As above, but lookup by name.
* --------------------------------
*/
static Relation
/* --------------------------------
* RelationIdGetRelation
*
- * return a relation descriptor based on its id.
- * return a cached value if possible
+ * Lookup a reldesc by OID; make one if not already in cache.
+ *
+ * NB: relation ref count is incremented, or set to 1 if new entry.
+ * Caller should eventually decrement count. (Usually,
+ * that happens by calling RelationClose().)
* --------------------------------
*/
Relation
/* --------------------------------
* RelationNameGetRelation
*
- * return a relation descriptor based on its name.
- * return a cached value if possible
+ * As above, but lookup by name.
* --------------------------------
*/
Relation
/* Free all the subsidiary data structures of the relcache entry */
FreeTupleDesc(relation->rd_att);
FreeTriggerDesc(relation);
- pfree(RelationGetLockInfo(relation));
pfree(RelationGetForm(relation));
/* If we're really done with the relcache entry, blow it away.
if (oldcxt != (MemoryContext) CacheCxt)
elog(NOIND, "RelationRegisterRelation: WARNING: Context != CacheCxt");
- RelationCacheInsert(relation);
-
RelationInitLockInfo(relation);
+ RelationCacheInsert(relation);
+
/*
* we've just created the relation. It is invisible to anyone else
* before the transaction is committed. Setting rd_myxactonly allows
(RegProcedure) F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(relation)));
- adrel = heap_openr(AttrDefaultRelationName);
+ adrel = heap_openr(AttrDefaultRelationName, AccessShareLock);
irel = index_openr(AttrDefaultIndex);
sd = index_beginscan(irel, false, 1, &skey);
tuple.t_data = NULL;
index_endscan(sd);
pfree(sd);
index_close(irel);
- heap_close(adrel);
+ heap_close(adrel, AccessShareLock);
}
static void
(RegProcedure) F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(relation)));
- rcrel = heap_openr(RelCheckRelationName);
+ rcrel = heap_openr(RelCheckRelationName, AccessShareLock);
irel = index_openr(RelCheckIndex);
sd = index_beginscan(irel, false, 1, &skey);
tuple.t_data = NULL;
index_endscan(sd);
pfree(sd);
index_close(irel);
- heap_close(rcrel);
-
+ heap_close(rcrel, AccessShareLock);
}
/*
/* the file descriptor is not yet opened */
ird->rd_fd = -1;
- /* lock info is not initialized */
- ird->lockInfo = (char *) NULL;
-
/* next, read the access method tuple form */
if ((nread = FileRead(fd, (char *) &len, sizeof(len))) != sizeof(len))
{
ird->rd_support = support;
- RelationCacheInsert(ird);
RelationInitLockInfo(ird);
+
+ RelationCacheInsert(ird);
}
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.35 1999/09/04 22:00:30 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.36 1999/09/18 19:07:55 tgl Exp $
*
* NOTES
* These routines allow the parser/planner/executor to perform
Datum attributeValue;
void *returnValue;
- tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
+ /*
+ * Open the relation first, to ensure we are in sync with SI inval
+ * events --- we don't want the tuple found in the cache to be
+ * invalidated out from under us.
+ */
cacheName = cacheinfo[cacheId].name;
+ relation = heap_openr(cacheName, AccessShareLock);
+
+ tp = SearchSysCacheTuple(cacheId, key1, key2, key3, key4);
if (!HeapTupleIsValid(tp))
{
+ heap_close(relation, AccessShareLock);
#ifdef CACHEDEBUG
elog(DEBUG,
"SearchSysCacheGetAttribute: Lookup in %s(%d) failed",
return NULL;
}
- relation = heap_openr(cacheName);
-
if (attributeNumber < 0 &&
attributeNumber > FirstLowInvalidHeapAttributeNumber)
{
}
else
{
+ heap_close(relation, AccessShareLock);
elog(ERROR,
"SearchSysCacheGetAttribute: Bad attr # %d in %s(%d)",
attributeNumber, cacheName, cacheId);
if (isNull)
{
-
/*
* Used to be an elog(DEBUG, ...) here and a claim that it should
* be a FATAL error, I don't think either is warranted -mer 6/9/92
*/
+ heap_close(relation, AccessShareLock);
return NULL;
}
returnValue = (void *) tmp;
}
- heap_close(relation);
+ heap_close(relation, AccessShareLock);
return returnValue;
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/*
* The procedure isn't a builtin, so we'll have to do a catalog lookup
- * to find its pg_proc entry.
+ * to find its pg_proc entry. Moreover, since probin is varlena, we're
+ * going to have to use heap_getattr, which means we need the reldesc,
+ * which means we need to open the relation. So we might as well do that
+ * first and get the benefit of SI inval if needed.
*/
+ rel = heap_openr(ProcedureRelationName, AccessShareLock);
+
procedureTuple = SearchSysCacheTuple(PROOID,
ObjectIdGetDatum(procedureId),
0, 0, 0);
procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
proname = procedureStruct->proname.data;
pronargs_save = *pronargs = procedureStruct->pronargs;
-
- /*
- * Extract the procedure info from the pg_proc tuple. Since probin is
- * varlena, do a amgetattr() on the procedure tuple. To do that, we
- * need the rel for the procedure relation, so...
- */
-
- /* open pg_procedure */
-
- rel = heap_openr(ProcedureRelationName);
- if (!RelationIsValid(rel))
- {
- elog(ERROR, "fmgr: Could not open relation %s",
- ProcedureRelationName);
- return (func_ptr) NULL;
- }
probinattr = heap_getattr(procedureTuple,
Anum_pg_proc_probin,
RelationGetDescr(rel), &isnull);
if (!PointerIsValid(probinattr) /* || isnull */ )
{
- heap_close(rel);
+ heap_close(rel, AccessShareLock);
elog(ERROR, "fmgr: Could not extract probin for %u from %s",
procedureId, ProcedureRelationName);
return (func_ptr) NULL;
}
probinstring = textout((struct varlena *) probinattr);
+ heap_close(rel, AccessShareLock);
+
user_fn = handle_load(probinstring, proname);
+ pfree(probinstring);
+
procedureId_save = procedureId;
user_fn_save = user_fn;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
HeapScanDesc scan;
ScanKeyData scanKey;
- dbrel = heap_openr(DatabaseRelationName);
- if (!RelationIsValid(dbrel))
- elog(FATAL, "GetDatabaseInfo: cannot open relation \"%-.*s\"",
- DatabaseRelationName);
+ dbrel = heap_openr(DatabaseRelationName, AccessShareLock);
ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_database_datname,
F_NAMEEQ, NameGetDatum(name));
{
elog(NOTICE, "GetDatabaseInfo: %s entry not found %s",
DatabaseRelationName, name);
+ heap_close(dbrel, AccessShareLock);
return TRUE;
}
memcpy(dbpath, VARDATA(dbtext), (VARSIZE(dbtext) - VARHDRSZ));
*(dbpath + (VARSIZE(dbtext) - VARHDRSZ)) = '\0';
- heap_close(dbrel);
+ heap_close(dbrel, AccessShareLock);
owner = palloc(sizeof(Oid));
*owner = dbowner;
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#include "access/relscan.h"
#include "access/tupmacs.h"
#include "storage/block.h"
+#include "storage/lmgr.h"
#include "utils/rel.h"
#include "utils/tqual.h"
/* heapam.c */
-extern Relation heap_open(Oid relationId);
-extern Relation heap_openr(char *relationName);
-extern void heap_close(Relation relation);
+extern Relation heap_open(Oid relationId, LOCKMODE lockmode);
+extern Relation heap_openr(char *relationName, LOCKMODE lockmode);
+extern void heap_close(Relation relation, LOCKMODE lockmode);
extern HeapScanDesc heap_beginscan(Relation relation, int atend,
Snapshot snapshot, unsigned nkeys, ScanKey key);
extern void heap_rescan(HeapScanDesc scan, bool scanFromEnd, ScanKey key);
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: buf_internals.h,v 1.31 1999/07/16 17:07:37 momjian Exp $
+ * $Id: buf_internals.h,v 1.32 1999/09/18 19:08:18 tgl Exp $
*
* NOTE
* If BUFFERPAGE0 is defined, then 0 will be used as a
#define INIT_BUFFERTAG(a,xx_reln,xx_blockNum) \
( \
- (a)->blockNum = xx_blockNum, \
- (a)->relId = ((LockInfo)(xx_reln->lockInfo))->lockRelId \
+ (a)->blockNum = (xx_blockNum), \
+ (a)->relId = (xx_reln)->rd_lockInfo.lockRelId \
)
#define BAD_BUFFER_ID(bid) ((bid<1) || (bid>(NBuffers)))
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: lmgr.h,v 1.22 1999/07/15 23:04:11 momjian Exp $
+ * $Id: lmgr.h,v 1.23 1999/09/18 19:08:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "storage/lock.h"
#include "utils/rel.h"
+/* These are the valid values of type LOCKMODE: */
+
+/* NoLock is not a lock mode, but a flag value meaning "don't get a lock" */
+#define NoLock 0
+
#define AccessShareLock 1 /* SELECT */
#define RowShareLock 2 /* SELECT FOR UPDATE */
#define RowExclusiveLock 3 /* INSERT, UPDATE, DELETE */
extern LOCKMETHOD LockTableId;
-typedef struct LockRelId
-{
- Oid relId; /* a relation identifier */
- Oid dbId; /* a database identifier */
-} LockRelId;
-
-typedef struct LockInfoData
-{
- LockRelId lockRelId;
-} LockInfoData;
-
-typedef LockInfoData *LockInfo;
-
-#define LockInfoIsValid(lockinfo) PointerIsValid(lockinfo)
-
extern LOCKMETHOD InitLockTable(void);
extern void RelationInitLockInfo(Relation relation);
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: rel.h,v 1.25 1999/07/16 17:07:40 momjian Exp $
+ * $Id: rel.h,v 1.26 1999/09/18 19:08:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "rewrite/prs2lock.h"
#include "storage/fd.h"
+
+/*
+ * LockRelId and LockInfo really belong to lmgr.h, but it's more convenient
+ * to declare them here so we can have a LockInfoData field in a Relation.
+ */
+
+typedef struct LockRelId
+{
+ Oid relId; /* a relation identifier */
+ Oid dbId; /* a database identifier */
+} LockRelId;
+
+typedef struct LockInfoData
+{
+ LockRelId lockRelId;
+} LockInfoData;
+
+typedef LockInfoData *LockInfo;
+
+
typedef struct Trigger
{
char *tgname;
Trigger *triggers;
} TriggerDesc;
+
typedef struct RelationData
{
File rd_fd; /* open file descriptor */
int rd_nblocks; /* number of blocks in rel */
uint16 rd_refcnt; /* reference count */
- bool rd_myxactonly; /* uses the local buffer mgr */
+ bool rd_myxactonly; /* rel uses the local buffer mgr */
bool rd_isnailed; /* rel is nailed in cache */
bool rd_isnoname; /* rel has no name */
bool rd_nonameunlinked; /* noname rel already unlinked */
Form_pg_am rd_am; /* AM tuple */
Form_pg_class rd_rel; /* RELATION tuple */
- Oid rd_id; /* relations's object id */
- Pointer lockInfo; /* ptr. to misc. info. */
- TupleDesc rd_att; /* tuple desciptor */
+ Oid rd_id; /* relation's object id */
+ LockInfoData rd_lockInfo; /* lock manager's info for locking relation */
+ TupleDesc rd_att; /* tuple descriptor */
RuleLock *rd_rules; /* rewrite rules */
IndexStrategy rd_istrat;
RegProcedure *rd_support;
typedef RelationData *Relation;
+
/* ----------------
* RelationPtr is used in the executor to support index scans
* where we have to keep track of several index relations in an
*/
typedef Relation *RelationPtr;
-#define InvalidRelation ((Relation)NULL)
/*
* RelationIsValid
*/
#define RelationIsValid(relation) PointerIsValid(relation)
+#define InvalidRelation ((Relation) NULL)
+
/*
* RelationGetSystemPort
* Returns system port of a relation.
*/
#define RelationGetSystemPort(relation) ((relation)->rd_fd)
-/*
- * RelationGetLockInfo
- * Returns the lock information structure in the reldesc
- *
- */
-#define RelationGetLockInfo(relation) ((relation)->lockInfo)
-
/*
* RelationHasReferenceCountZero
* True iff relation reference count is zero.
* RelationSetReferenceCount
* Sets relation reference count.
*/
-#define RelationSetReferenceCount(relation,count) ((relation)->rd_refcnt = count)
+#define RelationSetReferenceCount(relation,count) ((relation)->rd_refcnt = (count))
/*
* RelationIncrementReferenceCount
* Increments relation reference count.
*/
-#define RelationIncrementReferenceCount(relation) ((relation)->rd_refcnt += 1);
+#define RelationIncrementReferenceCount(relation) ((relation)->rd_refcnt += 1)
/*
* RelationDecrementReferenceCount
*/
#define RelationGetForm(relation) ((relation)->rd_rel)
-
/*
* RelationGetRelid
*
*/
#define RelationGetFile(relation) ((relation)->rd_fd)
-
/*
* RelationGetRelationName
*
#define RelationGetRelationName(relation) (&(relation)->rd_rel->relname)
/*
- * RelationGetRelationName
+ * RelationGetNumberOfAttributes
*
- * Returns a the number of attributes.
+ * Returns the number of attributes.
*/
#define RelationGetNumberOfAttributes(relation) ((relation)->rd_rel->relnatts)
/*
* RelationGetDescr
* Returns tuple descriptor for a relation.
- *
- * Note:
- * Assumes relation descriptor is valid.
*/
#define RelationGetDescr(relation) ((relation)->rd_att)
+
extern IndexStrategy RelationGetIndexStrategy(Relation relation);
extern void RelationSetIndexSupport(Relation relation, IndexStrategy strategy,