summaryrefslogtreecommitdiff
path: root/src/backend/commands
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands')
-rw-r--r--src/backend/commands/async.c93
-rw-r--r--src/backend/commands/cluster.c56
-rw-r--r--src/backend/commands/command.c63
-rw-r--r--src/backend/commands/copy.c31
-rw-r--r--src/backend/commands/creatinh.c34
-rw-r--r--src/backend/commands/dbcommands.c27
-rw-r--r--src/backend/commands/explain.c7
-rw-r--r--src/backend/commands/indexcmds.c8
-rw-r--r--src/backend/commands/proclang.c12
-rw-r--r--src/backend/commands/remove.c52
-rw-r--r--src/backend/commands/rename.c48
-rw-r--r--src/backend/commands/sequence.c28
-rw-r--r--src/backend/commands/trigger.c55
-rw-r--r--src/backend/commands/user.c143
-rw-r--r--src/backend/commands/vacuum.c44
15 files changed, 323 insertions, 378 deletions
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index ebdd045ce4..f8196f86ab 100644
--- a/src/backend/commands/async.c
+++ b/src/backend/commands/async.c
@@ -6,7 +6,7 @@
* Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.53 1999/07/18 18:03:49 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.54 1999/09/18 19:06:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -51,16 +51,9 @@
* transaction, since by assumption it is only called from outside any
* transaction.
*
- * Note that the system's use of pg_listener is confined to very short
- * intervals at the end of a transaction that contains NOTIFY statements,
- * or during the transaction caused by an inbound SIGUSR2. So the fact that
- * pg_listener is a global resource shouldn't cause too much performance
- * problem. But application authors ought to be discouraged from doing
- * LISTEN or UNLISTEN near the start of a long transaction --- that would
- * result in holding the pg_listener write lock for a long time, possibly
- * blocking unrelated activity. It could even lead to deadlock against another
- * transaction that touches the same user tables and then tries to NOTIFY.
- * Probably best to do LISTEN or UNLISTEN outside of transaction blocks.
+ * Although we grab AccessExclusiveLock on pg_listener for any operation,
+ * the lock is never held very long, so it shouldn't cause too much of
+ * a performance problem.
*
* An application that listens on the same relname it notifies will get
* NOTIFY messages for its own NOTIFYs. These can be ignored, if not useful,
@@ -155,26 +148,21 @@ Async_Notify(char *relname)
TPRINTF(TRACE_NOTIFY, "Async_Notify: %s", relname);
- /*
- * We allocate list memory from the global malloc pool to ensure that
- * it will live until we want to use it. This is probably not
- * necessary any longer, since we will use it before the end of the
- * transaction. DLList only knows how to use malloc() anyway, but we
- * could probably palloc() the strings...
- */
if (!pendingNotifies)
pendingNotifies = DLNewList();
- notifyName = strdup(relname);
- DLAddHead(pendingNotifies, DLNewElem(notifyName));
-
- /*
- * NOTE: we could check to see if pendingNotifies already has an entry
- * for relname, and thus avoid making duplicate entries. However,
- * most apps probably don't notify the same name multiple times per
- * transaction, so we'd likely just be wasting cycles to make such a
- * check. AsyncExistsPendingNotify() doesn't really care whether the
- * list contains duplicates...
- */
+ /* no point in making duplicate entries in the list ... */
+ if (!AsyncExistsPendingNotify(relname))
+ {
+ /*
+ * We allocate list memory from the global malloc pool to ensure
+ * that it will live until we want to use it. This is probably not
+ * necessary any longer, since we will use it before the end of the
+ * transaction. DLList only knows how to use malloc() anyway, but we
+ * could probably palloc() the strings...
+ */
+ notifyName = strdup(relname);
+ DLAddHead(pendingNotifies, DLNewElem(notifyName));
+ }
}
/*
@@ -212,8 +200,7 @@ Async_Listen(char *relname, int pid)
TPRINTF(TRACE_NOTIFY, "Async_Listen: %s", relname);
- lRel = heap_openr(ListenerRelationName);
- LockRelation(lRel, AccessExclusiveLock);
+ lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
tdesc = RelationGetDescr(lRel);
/* Detect whether we are already listening on this relname */
@@ -236,9 +223,8 @@ Async_Listen(char *relname, int pid)
if (alreadyListener)
{
+ heap_close(lRel, AccessExclusiveLock);
elog(NOTICE, "Async_Listen: We are already listening on %s", relname);
- UnlockRelation(lRel, AccessExclusiveLock);
- heap_close(lRel);
return;
}
@@ -262,8 +248,7 @@ Async_Listen(char *relname, int pid)
heap_insert(lRel, newtup);
pfree(newtup);
- UnlockRelation(lRel, AccessExclusiveLock);
- heap_close(lRel);
+ heap_close(lRel, AccessExclusiveLock);
/*
* now that we are listening, make sure we will unlisten before dying.
@@ -308,18 +293,14 @@ Async_Unlisten(char *relname, int pid)
TPRINTF(TRACE_NOTIFY, "Async_Unlisten %s", relname);
+ lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
/* Note we assume there can be only one matching tuple. */
lTuple = SearchSysCacheTuple(LISTENREL, PointerGetDatum(relname),
Int32GetDatum(pid),
0, 0);
if (lTuple != NULL)
- {
- lRel = heap_openr(ListenerRelationName);
- LockRelation(lRel, AccessExclusiveLock);
heap_delete(lRel, &lTuple->t_self, NULL);
- UnlockRelation(lRel, AccessExclusiveLock);
- heap_close(lRel);
- }
+ heap_close(lRel, AccessExclusiveLock);
/*
* We do not complain about unlistening something not being listened;
@@ -354,8 +335,7 @@ Async_UnlistenAll()
TPRINTF(TRACE_NOTIFY, "Async_UnlistenAll");
- lRel = heap_openr(ListenerRelationName);
- LockRelation(lRel, AccessExclusiveLock);
+ lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
tdesc = RelationGetDescr(lRel);
/* Find and delete all entries with my listenerPID */
@@ -369,8 +349,7 @@ Async_UnlistenAll()
heap_delete(lRel, &lTuple->t_self, NULL);
heap_endscan(sRel);
- UnlockRelation(lRel, AccessExclusiveLock);
- heap_close(lRel);
+ heap_close(lRel, AccessExclusiveLock);
}
/*
@@ -462,8 +441,7 @@ AtCommit_Notify()
TPRINTF(TRACE_NOTIFY, "AtCommit_Notify");
- lRel = heap_openr(ListenerRelationName);
- LockRelation(lRel, AccessExclusiveLock);
+ lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
tdesc = RelationGetDescr(lRel);
sRel = heap_beginscan(lRel, 0, SnapshotNow, 0, (ScanKey) NULL);
@@ -542,10 +520,13 @@ AtCommit_Notify()
heap_endscan(sRel);
/*
- * We do not do RelationUnsetLockForWrite(lRel) here, because the
- * transaction is about to be committed anyway.
+ * We do NOT release the lock on pg_listener here; we need to hold it
+ * until end of transaction (which is about to happen, anyway) to
+ * ensure that notified backends see our tuple updates when they look.
+ * Else they might disregard the signal, which would make the
+ * application programmer very unhappy.
*/
- heap_close(lRel);
+ heap_close(lRel, NoLock);
ClearPendingNotifies();
@@ -756,8 +737,7 @@ ProcessIncomingNotify(void)
StartTransactionCommand();
- lRel = heap_openr(ListenerRelationName);
- LockRelation(lRel, AccessExclusiveLock);
+ lRel = heap_openr(ListenerRelationName, AccessExclusiveLock);
tdesc = RelationGetDescr(lRel);
/* Scan only entries with my listenerPID */
@@ -794,10 +774,13 @@ ProcessIncomingNotify(void)
heap_endscan(sRel);
/*
- * We do not do RelationUnsetLockForWrite(lRel) here, because the
- * transaction is about to be committed anyway.
+ * We do NOT release the lock on pg_listener here; we need to hold it
+ * until end of transaction (which is about to happen, anyway) to
+ * ensure that other backends see our tuple updates when they look.
+ * Otherwise, a transaction started after this one might mistakenly
+ * think it doesn't need to send this backend a new NOTIFY.
*/
- heap_close(lRel);
+ heap_close(lRel, NoLock);
CommitTransactionCommand();
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index 6f99a920f5..d578fc263f 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -14,7 +14,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.44 1999/07/17 20:16:51 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.45 1999/09/18 19:06:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -101,29 +101,20 @@ cluster(char *oldrelname, char *oldindexname)
/*
* Like vacuum, cluster spans transactions, so I'm going to handle it
- * in the same way.
+ * in the same way: commit and restart transactions where needed.
+ *
+ * We grab exclusive access to the target rel and index for the
+ * duration of the initial transaction.
*/
- /* matches the StartTransaction in PostgresMain() */
-
- OldHeap = heap_openr(oldrelname);
- if (!RelationIsValid(OldHeap))
- {
- elog(ERROR, "cluster: unknown relation: \"%s\"",
- oldrelname);
- }
- OIDOldHeap = RelationGetRelid(OldHeap); /* Get OID for the index
- * scan */
+ OldHeap = heap_openr(oldrelname, AccessExclusiveLock);
+ OIDOldHeap = RelationGetRelid(OldHeap);
OldIndex = index_openr(oldindexname); /* Open old index relation */
- if (!RelationIsValid(OldIndex))
- {
- elog(ERROR, "cluster: unknown index: \"%s\"",
- oldindexname);
- }
- OIDOldIndex = RelationGetRelid(OldIndex); /* OID for the index scan */
+ LockRelation(OldIndex, AccessExclusiveLock);
+ OIDOldIndex = RelationGetRelid(OldIndex);
- heap_close(OldHeap);
+ heap_close(OldHeap, NoLock); /* do NOT give up the locks */
index_close(OldIndex);
/*
@@ -132,7 +123,7 @@ cluster(char *oldrelname, char *oldindexname)
* will get the lock after being blocked and add rows which won't be
* present in the new table. Bleagh! I'd be best to try and ensure
* that no-one's in the tables for the entire duration of this process
- * with a pg_vlock.
+ * with a pg_vlock. XXX Isn't the above comment now invalid?
*/
NewHeap = copy_heap(OIDOldHeap);
OIDNewHeap = RelationGetRelid(NewHeap);
@@ -171,7 +162,7 @@ cluster(char *oldrelname, char *oldindexname)
renamerel(NewIndexName, saveoldindexname);
/*
- * Again flush all the buffers.
+ * Again flush all the buffers. XXX perhaps not needed?
*/
CommitTransactionCommand();
StartTransactionCommand();
@@ -193,7 +184,7 @@ copy_heap(Oid OIDOldHeap)
*/
snprintf(NewName, NAMEDATALEN, "temp_%x", OIDOldHeap);
- OldHeap = heap_open(OIDOldHeap);
+ OldHeap = heap_open(OIDOldHeap, AccessExclusiveLock);
OldHeapDesc = RelationGetDescr(OldHeap);
/*
@@ -209,10 +200,11 @@ copy_heap(Oid OIDOldHeap)
if (!OidIsValid(OIDNewHeap))
elog(ERROR, "clusterheap: cannot create temporary heap relation\n");
- NewHeap = heap_open(OIDNewHeap);
+ /* XXX why are we bothering to do this: */
+ NewHeap = heap_open(OIDNewHeap, AccessExclusiveLock);
- heap_close(NewHeap);
- heap_close(OldHeap);
+ heap_close(NewHeap, AccessExclusiveLock);
+ heap_close(OldHeap, AccessExclusiveLock);
return NewHeap;
}
@@ -233,7 +225,7 @@ copy_index(Oid OIDOldIndex, Oid OIDNewHeap)
int natts;
FuncIndexInfo *finfo;
- NewHeap = heap_open(OIDNewHeap);
+ NewHeap = heap_open(OIDNewHeap, AccessExclusiveLock);
OldIndex = index_open(OIDOldIndex);
/*
@@ -305,8 +297,8 @@ copy_index(Oid OIDOldIndex, Oid OIDNewHeap)
Old_pg_index_Form->indisunique,
Old_pg_index_Form->indisprimary);
- heap_close(OldIndex);
- heap_close(NewHeap);
+ index_close(OldIndex);
+ heap_close(NewHeap, AccessExclusiveLock);
}
@@ -326,8 +318,8 @@ rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
* Open the relations I need. Scan through the OldHeap on the OldIndex
* and insert each tuple into the NewHeap.
*/
- LocalNewHeap = (Relation) heap_open(OIDNewHeap);
- LocalOldHeap = (Relation) heap_open(OIDOldHeap);
+ LocalNewHeap = heap_open(OIDNewHeap, AccessExclusiveLock);
+ LocalOldHeap = heap_open(OIDOldHeap, AccessExclusiveLock);
LocalOldIndex = (Relation) index_open(OIDOldIndex);
ScanDesc = index_beginscan(LocalOldIndex, false, 0, (ScanKey) NULL);
@@ -344,6 +336,6 @@ rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex)
index_endscan(ScanDesc);
index_close(LocalOldIndex);
- heap_close(LocalOldHeap);
- heap_close(LocalNewHeap);
+ heap_close(LocalOldHeap, AccessExclusiveLock);
+ heap_close(LocalNewHeap, AccessExclusiveLock);
}
diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c
index 7fe62cf124..8872bcdfac 100644
--- a/src/backend/commands/command.c
+++ b/src/backend/commands/command.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.53 1999/09/04 21:19:33 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.54 1999/09/18 19:06:40 tgl Exp $
*
* NOTES
* The PortalExecutorHeapMemory crap needs to be eliminated
@@ -283,6 +283,7 @@ PerformAddAttribute(char *relationName,
{
Relation rel,
attrdesc;
+ Oid myrelid;
HeapTuple reltup;
HeapTuple attributeTuple;
Form_pg_attribute attribute;
@@ -311,6 +312,14 @@ PerformAddAttribute(char *relationName,
#endif
/*
+ * Grab an exclusive lock on the target table, which we will NOT release
+ * until end of transaction.
+ */
+ rel = heap_openr(relationName, AccessExclusiveLock);
+ myrelid = RelationGetRelid(rel);
+ heap_close(rel, NoLock); /* close rel but keep lock! */
+
+ /*
* we can't add a not null attribute
*/
if (colDef->is_not_null)
@@ -331,20 +340,10 @@ PerformAddAttribute(char *relationName,
{
if (inherits)
{
- Oid myrelid,
- childrelid;
+ Oid childrelid;
List *child,
*children;
- rel = heap_openr(relationName);
- if (!RelationIsValid(rel))
- {
- elog(ERROR, "PerformAddAttribute: unknown relation: \"%s\"",
- relationName);
- }
- myrelid = RelationGetRelid(rel);
- heap_close(rel);
-
/* this routine is actually in the planner */
children = find_all_inheritors(lconsi(myrelid, NIL), NIL);
@@ -358,31 +357,23 @@ PerformAddAttribute(char *relationName,
childrelid = lfirsti(child);
if (childrelid == myrelid)
continue;
- rel = heap_open(childrelid);
- if (!RelationIsValid(rel))
- {
- elog(ERROR, "PerformAddAttribute: can't find catalog entry for inheriting class with oid %u",
- childrelid);
- }
+ rel = heap_open(childrelid, AccessExclusiveLock);
PerformAddAttribute((rel->rd_rel->relname).data,
userName, false, colDef);
- heap_close(rel);
+ heap_close(rel, AccessExclusiveLock);
}
}
}
- rel = heap_openr(RelationRelationName);
+ rel = heap_openr(RelationRelationName, RowExclusiveLock);
reltup = SearchSysCacheTupleCopy(RELNAME,
PointerGetDatum(relationName),
0, 0, 0);
if (!HeapTupleIsValid(reltup))
- {
- heap_close(rel);
elog(ERROR, "PerformAddAttribute: relation \"%s\" not found",
relationName);
- }
/*
* XXX is the following check sufficient?
@@ -391,23 +382,15 @@ PerformAddAttribute(char *relationName,
{
elog(ERROR, "PerformAddAttribute: index relation \"%s\" not changed",
relationName);
- return;
}
minattnum = ((Form_pg_class) GETSTRUCT(reltup))->relnatts;
maxatts = minattnum + 1;
if (maxatts > MaxHeapAttributeNumber)
- {
- pfree(reltup);
- heap_close(rel);
elog(ERROR, "PerformAddAttribute: relations limited to %d attributes",
MaxHeapAttributeNumber);
- }
-
- attrdesc = heap_openr(AttributeRelationName);
- Assert(attrdesc);
- Assert(RelationGetForm(attrdesc));
+ attrdesc = heap_openr(AttributeRelationName, RowExclusiveLock);
/*
* Open all (if any) pg_attribute indices
@@ -438,12 +421,8 @@ PerformAddAttribute(char *relationName,
0, 0);
if (HeapTupleIsValid(tup))
- {
- heap_close(attrdesc);
- heap_close(rel);
elog(ERROR, "PerformAddAttribute: attribute \"%s\" already exists in class \"%s\"",
colDef->colname, relationName);
- }
/*
* check to see if it is an array attribute.
@@ -490,7 +469,8 @@ PerformAddAttribute(char *relationName,
if (hasindex)
CatalogCloseIndices(Num_pg_attr_indices, idescs);
- heap_close(attrdesc);
+
+ heap_close(attrdesc, RowExclusiveLock);
((Form_pg_class) GETSTRUCT(reltup))->relnatts = maxatts;
heap_replace(rel, &reltup->t_self, reltup, NULL);
@@ -501,7 +481,7 @@ PerformAddAttribute(char *relationName,
CatalogCloseIndices(Num_pg_class_indices, ridescs);
pfree(reltup);
- heap_close(rel);
+ heap_close(rel, RowExclusiveLock);
}
void
@@ -510,9 +490,9 @@ LockTableCommand(LockStmt *lockstmt)
Relation rel;
int aclresult;
- rel = heap_openr(lockstmt->relname);
- if (rel == NULL)
- elog(ERROR, "LOCK TABLE: relation %s can't be openned", lockstmt->relname);
+ rel = heap_openr(lockstmt->relname, NoLock);
+ if (! RelationIsValid(rel))
+ elog(ERROR, "Relation '%s' does not exist", lockstmt->relname);
if (lockstmt->mode == AccessShareLock)
aclresult = pg_aclcheck(lockstmt->relname, GetPgUserName(), ACL_RD);
@@ -524,4 +504,5 @@ LockTableCommand(LockStmt *lockstmt)
LockRelation(rel, lockstmt->mode);
+ heap_close(rel, NoLock); /* close rel, keep lock */
}
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 35f3d6da0b..493d2a170e 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -6,7 +6,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.87 1999/09/11 22:28:11 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.88 1999/09/18 19:06:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -251,22 +251,22 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
Relation rel;
extern char *UserName; /* defined in global.c */
const AclMode required_access = from ? ACL_WR : ACL_RD;
+ LOCKMODE required_lock = from ? AccessExclusiveLock : AccessShareLock;
+ /* Note: AccessExclusive is probably overkill for copying to a relation,
+ * but that's what the existing code grabs on the rel's indices. If
+ * this is relaxed then I think the index locks need relaxed also.
+ */
int result;
- rel = heap_openr(relname);
- if (rel == NULL)
- elog(ERROR, "COPY command failed. Class %s "
- "does not exist.", relname);
+ rel = heap_openr(relname, required_lock);
result = pg_aclcheck(relname, UserName, required_access);
if (result != ACLCHECK_OK)
elog(ERROR, "%s: %s", relname, aclcheck_error_strings[result]);
- /* Above should not return */
- else if (!superuser() && !pipe)
+ else if (!pipe && !superuser())
elog(ERROR, "You must have Postgres superuser privilege to do a COPY "
"directly to or from a file. Anyone can COPY to stdout or "
"from stdin. Psql's \\copy command also works for anyone.");
- /* Above should not return. */
else
{
if (from)
@@ -342,6 +342,8 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
pq_endcopyout(false);
}
}
+
+ heap_close(rel, required_lock);
}
@@ -500,8 +502,6 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
pfree(elements);
pfree(typmod);
}
-
- heap_close(rel);
}
static void
@@ -905,20 +905,19 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
pfree(typmod);
}
- /* comments in execUtils.c */
if (has_index)
{
for (i = 0; i < n_indices; i++)
{
if (index_rels[i] == NULL)
continue;
+ /* see comments in ExecOpenIndices() in execUtils.c */
if ((index_rels[i])->rd_rel->relam != BTREE_AM_OID &&
(index_rels[i])->rd_rel->relam != HASH_AM_OID)
UnlockRelation(index_rels[i], AccessExclusiveLock);
index_close(index_rels[i]);
}
}
- heap_close(rel);
}
@@ -991,7 +990,7 @@ IsTypeByVal(Oid type)
/*
* Given the OID of a relation, return an array of index relation descriptors
* and the number of index relations. These relation descriptors are open
- * using heap_open().
+ * using index_open().
*
* Space for the array itself is palloc'ed.
*/
@@ -1017,7 +1016,7 @@ GetIndexRelations(Oid main_relation_oid,
int i;
bool isnull;
- pg_index_rel = heap_openr(IndexRelationName);
+ pg_index_rel = heap_openr(IndexRelationName, AccessShareLock);
scandesc = heap_beginscan(pg_index_rel, 0, SnapshotNow, 0, NULL);
tupDesc = RelationGetDescr(pg_index_rel);
@@ -1044,7 +1043,7 @@ GetIndexRelations(Oid main_relation_oid,
}
heap_endscan(scandesc);
- heap_close(pg_index_rel);
+ heap_close(pg_index_rel, AccessShareLock);
/* We cannot trust to relhasindex of the main_relation now, so... */
if (*n_indices == 0)
@@ -1055,7 +1054,7 @@ GetIndexRelations(Oid main_relation_oid,
for (i = 0, scan = head; i < *n_indices; i++, scan = scan->next)
{
(*index_rels)[i] = index_open(scan->index_rel_oid);
- /* comments in execUtils.c */
+ /* see comments in ExecOpenIndices() in execUtils.c */
if ((*index_rels)[i] != NULL &&
((*index_rels)[i])->rd_rel->relam != BTREE_AM_OID &&
((*index_rels)[i])->rd_rel->relam != HASH_AM_OID)
diff --git a/src/backend/commands/creatinh.c b/src/backend/commands/creatinh.c
index b93a40e7ba..c1069dd41e 100644
--- a/src/backend/commands/creatinh.c
+++ b/src/backend/commands/creatinh.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.45 1999/07/17 20:16:52 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.46 1999/09/18 19:06:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -202,14 +202,13 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
*/
foreach(entry, schema)
{
- List *rest;
ColumnDef *coldef = lfirst(entry);
+ List *rest;
foreach(rest, lnext(entry))
{
-
/*
- * check for duplicated relation names
+ * check for duplicated names within the new relation
*/
ColumnDef *restdef = lfirst(rest);
@@ -246,17 +245,14 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
TupleDesc tupleDesc;
TupleConstr *constr;
- relation = heap_openr(name);
- if (relation == NULL)
- {
- elog(ERROR,
- "MergeAttr: Can't inherit from non-existent superclass '%s'", name);
- }
- if (relation->rd_rel->relkind == 'S')
- elog(ERROR, "MergeAttr: Can't inherit from sequence superclass '%s'", name);
+ relation = heap_openr(name, AccessShareLock);
tupleDesc = RelationGetDescr(relation);
constr = tupleDesc->constr;
+ /* XXX shouldn't this test be stricter? No indexes, for example? */
+ if (relation->rd_rel->relkind == 'S')
+ elog(ERROR, "MergeAttr: Can't inherit from sequence superclass '%s'", name);
+
for (attrno = relation->rd_rel->relnatts - 1; attrno >= 0; attrno--)
{
Form_pg_attribute attribute = tupleDesc->attrs[attrno];
@@ -340,9 +336,11 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
}
/*
- * iteration cleanup and result collection
+ * Close the parent rel, but keep our AccessShareLock on it until
+ * xact commit. That will prevent someone else from deleting or
+ * ALTERing the parent before the child is committed.
*/
- heap_close(relation);
+ heap_close(relation, NoLock);
/*
* wants the inherited schema to appear in the order they are
@@ -386,7 +384,7 @@ StoreCatalogInheritance(Oid relationId, List *supers)
* Catalog INHERITS information.
* ----------------
*/
- relation = heap_openr(InheritsRelationName);
+ relation = heap_openr(InheritsRelationName, RowExclusiveLock);
desc = RelationGetDescr(relation);
seqNumber = 1;
@@ -422,7 +420,7 @@ StoreCatalogInheritance(Oid relationId, List *supers)
seqNumber += 1;
}
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
/* ----------------
* Catalog IPL information.
@@ -510,7 +508,7 @@ again:
* 3.
* ----------------
*/
- relation = heap_openr(InheritancePrecidenceListRelationName);
+ relation = heap_openr(InheritancePrecidenceListRelationName, RowExclusiveLock);
desc = RelationGetDescr(relation);
seqNumber = 1;
@@ -537,7 +535,7 @@ again:
seqNumber += 1;
}
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
}
/*
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index b779715fe8..24eb5b531d 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.39 1999/07/17 20:16:52 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.40 1999/09/18 19:06:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -103,6 +103,8 @@ destroydb(char *dbname, CommandDest dest)
/* stop the vacuum daemon */
stop_vacuum(dbpath, dbname);
+ /* XXX what about stopping backends connected to the target database? */
+
path = ExpandDatabasePath(dbpath);
if (path == NULL)
elog(ERROR, "Unable to locate path '%s'"
@@ -189,6 +191,7 @@ check_permissions(char *command,
utup = SearchSysCacheTuple(USENAME,
PointerGetDatum(userName),
0, 0, 0);
+ Assert(utup);
*userIdP = ((Form_pg_shadow) GETSTRUCT(utup))->usesysid;
use_super = ((Form_pg_shadow) GETSTRUCT(utup))->usesuper;
use_createdb = ((Form_pg_shadow) GETSTRUCT(utup))->usecreatedb;
@@ -211,22 +214,13 @@ check_permissions(char *command,
/* Check to make sure database is owned by this user */
/*
- * need the reldesc to get the database owner out of dbtup and to set
- * a write lock on it.
+ * Acquire exclusive lock on pg_database from the beginning, even though
+ * we only need read access right here, to avoid potential deadlocks
+ * from upgrading our lock later. (Is this still necessary? Could we
+ * use something weaker than exclusive lock?)
*/
- dbrel = heap_openr(DatabaseRelationName);
-
- if (!RelationIsValid(dbrel))
- elog(FATAL, "%s: cannot open relation \"%-.*s\"",
- command, DatabaseRelationName);
+ dbrel = heap_openr(DatabaseRelationName, AccessExclusiveLock);
- /*
- * Acquire a write lock on pg_database from the beginning to avoid
- * upgrading a read lock to a write lock. Upgrading causes long
- * delays when multiple 'createdb's or 'destroydb's are run simult.
- * -mer 7/3/91
- */
- LockRelation(dbrel, AccessExclusiveLock);
dbtup = get_pg_dbtup(command, dbname, dbrel);
dbfound = HeapTupleIsValid(dbtup);
@@ -248,7 +242,8 @@ check_permissions(char *command,
else
*dbIdP = InvalidOid;
- heap_close(dbrel);
+ /* We will keep the lock on dbrel until end of transaction. */
+ heap_close(dbrel, NoLock);
/*
* Now be sure that the user is allowed to do this.
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 3b1da18783..11e5c39423 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -4,7 +4,7 @@
*
* Copyright (c) 1994-5, Regents of the University of California
*
- * $Id: explain.c,v 1.47 1999/09/11 19:06:36 tgl Exp $
+ * $Id: explain.c,v 1.48 1999/09/18 19:06:40 tgl Exp $
*
*/
@@ -211,11 +211,14 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es)
i = 0;
foreach(l, ((IndexScan *) plan)->indxid)
{
- relation = RelationIdCacheGetRelation((int) lfirst(l));
+ relation = RelationIdGetRelation(lfirsti(l));
+ Assert(relation);
if (++i > 1)
appendStringInfo(str, ", ");
appendStringInfo(str,
stringStringInfo((RelationGetRelationName(relation))->data));
+ /* drop relcache refcount from RelationIdGetRelation */
+ RelationDecrementReferenceCount(relation);
}
case T_SeqScan:
if (((Scan *) plan)->scanrelid > 0)
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 31d3419bee..113854311d 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.10 1999/08/22 20:14:37 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.11 1999/09/18 19:06:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -324,15 +324,15 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
FIsetProcOid(funcInfo, tuple->t_data->t_oid);
}
- heapRelation = heap_open(relationId);
+ heapRelation = heap_open(relationId, ShareLock);
indexRelation = index_open(indexId);
- LockRelation(heapRelation, ShareLock);
-
InitIndexStrategy(numberOfAttributes, indexRelation, accessMethodId);
index_build(heapRelation, indexRelation, numberOfAttributes,
attributeNumberA, 0, NULL, funcInfo, predInfo);
+
+ /* heap and index rels are closed as a side-effect of index_build */
}
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 21fde2af57..b2fc76f090 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -120,15 +120,14 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
values[i++] = ObjectIdGetDatum(procTup->t_data->t_oid);
values[i++] = (Datum) fmgr(F_TEXTIN, stmt->plcompiler);
- rel = heap_openr(LanguageRelationName);
+ rel = heap_openr(LanguageRelationName, RowExclusiveLock);
tupDesc = rel->rd_att;
tup = heap_formtuple(tupDesc, values, nulls);
heap_insert(rel, tup);
- heap_close(rel);
- return;
+ heap_close(rel, RowExclusiveLock);
}
@@ -160,6 +159,8 @@ DropProceduralLanguage(DropPLangStmt *stmt)
*/
case_translate_language_name(stmt->plname, languageName);
+ rel = heap_openr(LanguageRelationName, RowExclusiveLock);
+
langTup = SearchSysCacheTupleCopy(LANNAME,
PointerGetDatum(languageName),
0, 0, 0);
@@ -167,14 +168,11 @@ DropProceduralLanguage(DropPLangStmt *stmt)
elog(ERROR, "Language %s doesn't exist", languageName);
if (!((Form_pg_language) GETSTRUCT(langTup))->lanispl)
- {
elog(ERROR, "Language %s isn't a created procedural language",
languageName);
- }
- rel = heap_openr(LanguageRelationName);
heap_delete(rel, &langTup->t_self, NULL);
pfree(langTup);
- heap_close(rel);
+ heap_close(rel, RowExclusiveLock);
}
diff --git a/src/backend/commands/remove.c b/src/backend/commands/remove.c
index af20c79f17..a73964cb02 100644
--- a/src/backend/commands/remove.c
+++ b/src/backend/commands/remove.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.36 1999/07/17 20:16:53 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.37 1999/09/18 19:06:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -75,13 +75,14 @@ RemoveOperator(char *operatorName, /* operator name */
else
oprtype = 'r';
+ relation = heap_openr(OperatorRelationName, RowExclusiveLock);
+
tup = SearchSysCacheTupleCopy(OPRNAME,
PointerGetDatum(operatorName),
ObjectIdGetDatum(typeId1),
ObjectIdGetDatum(typeId2),
CharGetDatum(oprtype));
- relation = heap_openr(OperatorRelationName);
if (HeapTupleIsValid(tup))
{
#ifndef NO_SECURITY
@@ -117,7 +118,7 @@ RemoveOperator(char *operatorName, /* operator name */
}
}
pfree(tup);
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
}
#ifdef NOTYET
@@ -141,7 +142,7 @@ SingleOpOperatorRemove(Oid typeOid)
ScanKeyEntryInitialize(&key[0],
0, 0, F_OIDEQ, (Datum) typeOid);
- rel = heap_openr(OperatorRelationName);
+ rel = heap_openr(OperatorRelationName, RowExclusiveLock);
for (i = 0; i < 3; ++i)
{
key[0].sk_attno = attnums[i];
@@ -150,7 +151,7 @@ SingleOpOperatorRemove(Oid typeOid)
heap_delete(rel, &tup->t_self, NULL);
heap_endscan(scan);
}
- heap_close(rel);
+ heap_close(rel, RowExclusiveLock);
}
/*
@@ -187,7 +188,7 @@ AttributeAndRelationRemove(Oid typeOid)
oidptr = (struct oidlist *) palloc(sizeof(*oidptr));
oidptr->next = NULL;
optr = oidptr;
- rel = heap_openr(AttributeRelationName);
+ rel = heap_openr(AttributeRelationName, AccessShareLock);
scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
{
@@ -197,14 +198,15 @@ AttributeAndRelationRemove(Oid typeOid)
}
optr->next = NULL;
heap_endscan(scan);
- heap_close(rel);
+ heap_close(rel, AccessShareLock);
+ optr = oidptr;
ScanKeyEntryInitialize(&key[0], 0,
ObjectIdAttributeNumber,
F_OIDEQ, (Datum) 0);
- optr = oidptr;
- rel = heap_openr(RelationRelationName);
+ /* get RowExclusiveLock because heap_destroy will need it */
+ rel = heap_openr(RelationRelationName, RowExclusiveLock);
while (PointerIsValid((char *) optr->next))
{
key[0].sk_argument = (Datum) (optr++)->reloid;
@@ -217,9 +219,9 @@ AttributeAndRelationRemove(Oid typeOid)
name = (((Form_pg_class) GETSTRUCT(tup))->relname).data;
heap_destroy_with_catalog(name);
}
+ heap_endscan(scan);
}
- heap_endscan(scan);
- heap_close(rel);
+ heap_close(rel, RowExclusiveLock);
}
#endif /* NOTYET */
@@ -245,18 +247,17 @@ RemoveType(char *typeName) /* type name to be removed */
typeName);
#endif
- relation = heap_openr(TypeRelationName);
+ relation = heap_openr(TypeRelationName, RowExclusiveLock);
+
tup = SearchSysCacheTuple(TYPNAME,
PointerGetDatum(typeName),
0, 0, 0);
-
if (!HeapTupleIsValid(tup))
{
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
elog(ERROR, "RemoveType: type '%s' does not exist", typeName);
}
- relation = heap_openr(TypeRelationName);
typeOid = tup->t_data->t_oid;
heap_delete(relation, &tup->t_self, NULL);
@@ -267,14 +268,13 @@ RemoveType(char *typeName) /* type name to be removed */
0, 0, 0);
if (!HeapTupleIsValid(tup))
{
- heap_close(relation);
- elog(ERROR, "RemoveType: type '%s' does not exist", typeName);
+ heap_close(relation, RowExclusiveLock);
+ elog(ERROR, "RemoveType: type '%s' does not exist", shadow_type);
}
- typeOid = tup->t_data->t_oid;
heap_delete(relation, &tup->t_self, NULL);
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
}
/*
@@ -328,7 +328,7 @@ RemoveFunction(char *functionName, /* function name to be removed */
}
#endif
- relation = heap_openr(ProcedureRelationName);
+ relation = heap_openr(ProcedureRelationName, RowExclusiveLock);
tup = SearchSysCacheTuple(PRONAME,
PointerGetDatum(functionName),
Int32GetDatum(nargs),
@@ -337,19 +337,19 @@ RemoveFunction(char *functionName, /* function name to be removed */
if (!HeapTupleIsValid(tup))
{
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
func_error("RemoveFunction", functionName, nargs, argList, NULL);
}
if ((((Form_pg_proc) GETSTRUCT(tup))->prolang) == INTERNALlanguageId)
{
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
elog(ERROR, "RemoveFunction: function \"%s\" is built-in", functionName);
}
heap_delete(relation, &tup->t_self, NULL);
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
}
void
@@ -398,7 +398,7 @@ RemoveAggregate(char *aggName, char *aggType)
}
#endif
- relation = heap_openr(AggregateRelationName);
+ relation = heap_openr(AggregateRelationName, RowExclusiveLock);
tup = SearchSysCacheTuple(AGGNAME,
PointerGetDatum(aggName),
ObjectIdGetDatum(basetypeID),
@@ -406,7 +406,7 @@ RemoveAggregate(char *aggName, char *aggType)
if (!HeapTupleIsValid(tup))
{
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
if (aggType)
{
elog(ERROR, "RemoveAggregate: aggregate '%s' for '%s' does not exist",
@@ -420,5 +420,5 @@ RemoveAggregate(char *aggName, char *aggType)
}
heap_delete(relation, &tup->t_self, NULL);
- heap_close(relation);
+ heap_close(relation, RowExclusiveLock);
}
diff --git a/src/backend/commands/rename.c b/src/backend/commands/rename.c
index 1a93027b4a..3a822bd4e4 100644
--- a/src/backend/commands/rename.c
+++ b/src/backend/commands/rename.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.32 1999/07/17 20:16:53 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.33 1999/09/18 19:06:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -48,6 +48,7 @@ renameatt(char *relname,
char *userName,
int recurse)
{
+ Relation targetrelation;
Relation attrelation;
HeapTuple reltup,
oldatttup,
@@ -72,6 +73,14 @@ renameatt(char *relname,
#endif
/*
+ * Grab an exclusive lock on the target table, which we will NOT release
+ * until end of transaction.
+ */
+ targetrelation = heap_openr(relname, AccessExclusiveLock);
+ relid = RelationGetRelid(targetrelation);
+ heap_close(targetrelation, NoLock); /* close rel but keep lock! */
+
+ /*
* if the 'recurse' flag is set then we are supposed to rename this
* attribute in all classes that inherit from 'relname' (as well as in
* 'relname').
@@ -82,16 +91,11 @@ renameatt(char *relname,
*/
if (recurse)
{
- Oid myrelid,
- childrelid;
List *child,
*children;
- if ((myrelid = RelnameFindRelid(relname)) == InvalidOid)
- elog(ERROR, "renameatt: unknown relation: \"%s\"", relname);
-
/* this routine is actually in the planner */
- children = find_all_inheritors(lconsi(myrelid, NIL), NIL);
+ children = find_all_inheritors(lconsi(relid, NIL), NIL);
/*
* find_all_inheritors does the recursive search of the
@@ -100,10 +104,11 @@ renameatt(char *relname,
*/
foreach(child, children)
{
+ Oid childrelid;
char childname[NAMEDATALEN];
childrelid = lfirsti(child);
- if (childrelid == myrelid)
+ if (childrelid == relid)
continue;
reltup = SearchSysCacheTuple(RELOID,
ObjectIdGetDatum(childrelid),
@@ -117,14 +122,12 @@ renameatt(char *relname,
StrNCpy(childname,
((Form_pg_class) GETSTRUCT(reltup))->relname.data,
NAMEDATALEN);
- /* no more recursion! */
+ /* note we need not recurse again! */
renameatt(childname, oldattname, newattname, userName, 0);
}
}
-
- if ((relid = RelnameFindRelid(relname)) == InvalidOid)
- elog(ERROR, "renameatt: relation \"%s\" nonexistent", relname);
+ attrelation = heap_openr(AttributeRelationName, RowExclusiveLock);
oldatttup = SearchSysCacheTupleCopy(ATTNAME,
ObjectIdGetDatum(relid),
@@ -150,7 +153,6 @@ renameatt(char *relname,
StrNCpy((((Form_pg_attribute) (GETSTRUCT(oldatttup)))->attname.data),
newattname, NAMEDATALEN);
- attrelation = heap_openr(AttributeRelationName);
heap_replace(attrelation, &oldatttup->t_self, oldatttup, NULL);
/* keep system catalog indices current */
@@ -159,7 +161,7 @@ renameatt(char *relname,
CatalogCloseIndices(Num_pg_attr_indices, irelations);
pfree(oldatttup);
- heap_close(attrelation);
+ heap_close(attrelation, RowExclusiveLock);
}
/*
@@ -182,6 +184,7 @@ void
renamerel(char *oldrelname, char *newrelname)
{
int i;
+ Relation targetrelation;
Relation relrelation; /* for RELATION relation */
HeapTuple oldreltup;
char oldpath[MAXPGPATH],
@@ -198,6 +201,15 @@ renamerel(char *oldrelname, char *newrelname)
elog(ERROR, "renamerel: Illegal class name: \"%s\" -- pg_ is reserved for system catalogs",
newrelname);
+ /*
+ * Grab an exclusive lock on the target table, which we will NOT release
+ * until end of transaction.
+ */
+ targetrelation = heap_openr(oldrelname, AccessExclusiveLock);
+ heap_close(targetrelation, NoLock); /* close rel but keep lock! */
+
+ relrelation = heap_openr(RelationRelationName, RowExclusiveLock);
+
oldreltup = SearchSysCacheTupleCopy(RELNAME,
PointerGetDatum(oldrelname),
0, 0, 0);
@@ -207,12 +219,17 @@ renamerel(char *oldrelname, char *newrelname)
if (RelnameFindRelid(newrelname) != InvalidOid)
elog(ERROR, "renamerel: relation \"%s\" exists", newrelname);
+ /*
+ * XXX need to close relation and flush dirty buffers here!
+ */
+
/* rename the path first, so if this fails the rename's not done */
strcpy(oldpath, relpath(oldrelname));
strcpy(newpath, relpath(newrelname));
if (rename(oldpath, newpath) < 0)
elog(ERROR, "renamerel: unable to rename file: %s", oldpath);
+ /* rename additional segments of relation, too */
for (i = 1;; i++)
{
sprintf(toldpath, "%s.%d", oldpath, i);
@@ -225,7 +242,6 @@ renamerel(char *oldrelname, char *newrelname)
newrelname, NAMEDATALEN);
/* insert fixed rel tuple */
- relrelation = heap_openr(RelationRelationName);
heap_replace(relrelation, &oldreltup->t_self, oldreltup, NULL);
/* keep the system catalog indices current */
@@ -233,5 +249,5 @@ renamerel(char *oldrelname, char *newrelname)
CatalogIndexInsert(irelations, Num_pg_class_indices, relrelation, oldreltup);
CatalogCloseIndices(Num_pg_class_indices, irelations);
- heap_close(relrelation);
+ heap_close(relrelation, RowExclusiveLock);
}
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index b7f959cd65..be47d32f9f 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -153,10 +153,7 @@ DefineSequence(CreateSeqStmt *seq)
DefineRelation(stmt, RELKIND_SEQUENCE);
- rel = heap_openr(seq->seqname);
- Assert(RelationIsValid(rel));
-
- LockRelation(rel, AccessExclusiveLock);
+ rel = heap_openr(seq->seqname, AccessExclusiveLock);
tupDesc = RelationGetDescr(rel);
@@ -179,11 +176,7 @@ DefineSequence(CreateSeqStmt *seq)
if (WriteBuffer(buf) == STATUS_ERROR)
elog(ERROR, "DefineSequence: WriteBuffer failed");
- UnlockRelation(rel, AccessExclusiveLock);
- heap_close(rel);
-
- return;
-
+ heap_close(rel, AccessExclusiveLock);
}
@@ -422,12 +415,7 @@ init_sequence(char *caller, char *name)
temp = elm;
}
- temp->rel = heap_openr(name);
-
- if (!RelationIsValid(temp->rel))
- elog(ERROR, "%s.%s: sequence does not exist", name, caller);
-
- LockRelation(temp->rel, AccessShareLock);
+ temp->rel = heap_openr(name, AccessShareLock);
if (temp->rel->rd_rel->relkind != RELKIND_SEQUENCE)
elog(ERROR, "%s.%s: %s is not sequence !", name, caller, name);
@@ -453,7 +441,6 @@ init_sequence(char *caller, char *name)
}
return elm;
-
}
@@ -467,20 +454,15 @@ CloseSequences(void)
SeqTable elm;
Relation rel;
- for (elm = seqtab; elm != (SeqTable) NULL;)
+ for (elm = seqtab; elm != (SeqTable) NULL; elm = elm->next)
{
if (elm->rel != (Relation) NULL) /* opened in current xact */
{
rel = elm->rel;
elm->rel = (Relation) NULL;
- UnlockRelation(rel, AccessShareLock);
- heap_close(rel);
+ heap_close(rel, AccessShareLock);
}
- elm = elm->next;
}
-
- return;
-
}
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 55f67711c7..aa7a0b56c1 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -63,11 +63,7 @@ CreateTrigger(CreateTrigStmt *stmt)
elog(ERROR, "%s: %s", stmt->relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
#endif
- rel = heap_openr(stmt->relname);
- if (!RelationIsValid(rel))
- elog(ERROR, "CreateTrigger: there is no relation %s", stmt->relname);
-
- LockRelation(rel, AccessExclusiveLock);
+ rel = heap_openr(stmt->relname, AccessExclusiveLock);
TRIGGER_CLEAR_TYPE(tgtype);
if (stmt->before)
@@ -103,8 +99,7 @@ CreateTrigger(CreateTrigStmt *stmt)
}
/* Scan pg_trigger */
- tgrel = heap_openr(TriggerRelationName);
- LockRelation(tgrel, AccessExclusiveLock);
+ tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
F_OIDEQ, RelationGetRelid(rel));
tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
@@ -203,20 +198,19 @@ CreateTrigger(CreateTrigStmt *stmt)
CatalogIndexInsert(idescs, Num_pg_trigger_indices, tgrel, tuple);
CatalogCloseIndices(Num_pg_trigger_indices, idescs);
pfree(tuple);
- UnlockRelation(tgrel, AccessExclusiveLock);
- heap_close(tgrel);
+ heap_close(tgrel, RowExclusiveLock);
pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1]));
pfree(DatumGetPointer(values[Anum_pg_trigger_tgargs - 1]));
/* update pg_class */
+ pgrel = heap_openr(RelationRelationName, RowExclusiveLock);
tuple = SearchSysCacheTupleCopy(RELNAME,
PointerGetDatum(stmt->relname),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "CreateTrigger: relation %s not found in pg_class", stmt->relname);
- pgrel = heap_openr(RelationRelationName);
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1;
RelationInvalidateHeapTuple(pgrel, tuple);
heap_replace(pgrel, &tuple->t_self, tuple, NULL);
@@ -224,7 +218,7 @@ CreateTrigger(CreateTrigStmt *stmt)
CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
CatalogCloseIndices(Num_pg_class_indices, ridescs);
pfree(tuple);
- heap_close(pgrel);
+ heap_close(pgrel, RowExclusiveLock);
CommandCounterIncrement();
oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
@@ -232,8 +226,8 @@ CreateTrigger(CreateTrigStmt *stmt)
rel->rd_rel->reltriggers = found + 1;
RelationBuildTriggers(rel);
MemoryContextSwitchTo(oldcxt);
- heap_close(rel);
- return;
+ /* Keep lock on target rel until end of xact */
+ heap_close(rel, NoLock);
}
void
@@ -255,14 +249,9 @@ DropTrigger(DropTrigStmt *stmt)
elog(ERROR, "%s: %s", stmt->relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
#endif
- rel = heap_openr(stmt->relname);
- if (!RelationIsValid(rel))
- elog(ERROR, "DropTrigger: there is no relation %s", stmt->relname);
+ rel = heap_openr(stmt->relname, AccessExclusiveLock);
- LockRelation(rel, AccessExclusiveLock);
-
- tgrel = heap_openr(TriggerRelationName);
- LockRelation(tgrel, AccessExclusiveLock);
+ tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
F_OIDEQ, RelationGetRelid(rel));
tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
@@ -282,20 +271,19 @@ DropTrigger(DropTrigStmt *stmt)
elog(ERROR, "DropTrigger: there is no trigger %s on relation %s",
stmt->trigname, stmt->relname);
if (tgfound > 1)
- elog(NOTICE, "DropTrigger: found (and deleted) %d trigger %s on relation %s",
+ elog(NOTICE, "DropTrigger: found (and deleted) %d triggers %s on relation %s",
tgfound, stmt->trigname, stmt->relname);
heap_endscan(tgscan);
- UnlockRelation(tgrel, AccessExclusiveLock);
- heap_close(tgrel);
+ heap_close(tgrel, RowExclusiveLock);
+ /* update pg_class */
+ pgrel = heap_openr(RelationRelationName, RowExclusiveLock);
tuple = SearchSysCacheTupleCopy(RELNAME,
PointerGetDatum(stmt->relname),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "DropTrigger: relation %s not found in pg_class", stmt->relname);
- /* update pg_class */
- pgrel = heap_openr(RelationRelationName);
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found;
RelationInvalidateHeapTuple(pgrel, tuple);
heap_replace(pgrel, &tuple->t_self, tuple, NULL);
@@ -303,7 +291,7 @@ DropTrigger(DropTrigStmt *stmt)
CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
CatalogCloseIndices(Num_pg_class_indices, ridescs);
pfree(tuple);
- heap_close(pgrel);
+ heap_close(pgrel, RowExclusiveLock);
CommandCounterIncrement();
oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
@@ -312,8 +300,8 @@ DropTrigger(DropTrigStmt *stmt)
if (found > 0)
RelationBuildTriggers(rel);
MemoryContextSwitchTo(oldcxt);
- heap_close(rel);
- return;
+ /* Keep lock on target rel until end of xact */
+ heap_close(rel, NoLock);
}
void
@@ -324,8 +312,7 @@ RelationRemoveTriggers(Relation rel)
ScanKeyData key;
HeapTuple tup;
- tgrel = heap_openr(TriggerRelationName);
- LockRelation(tgrel, AccessExclusiveLock);
+ tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
F_OIDEQ, RelationGetRelid(rel));
@@ -335,9 +322,7 @@ RelationRemoveTriggers(Relation rel)
heap_delete(tgrel, &tup->t_self, NULL);
heap_endscan(tgscan);
- UnlockRelation(tgrel, AccessExclusiveLock);
- heap_close(tgrel);
-
+ heap_close(tgrel, RowExclusiveLock);
}
void
@@ -367,7 +352,7 @@ RelationBuildTriggers(Relation relation)
(RegProcedure) F_OIDEQ,
ObjectIdGetDatum(RelationGetRelid(relation)));
- tgrel = heap_openr(TriggerRelationName);
+ tgrel = heap_openr(TriggerRelationName, AccessShareLock);
irel = index_openr(TriggerRelidIndex);
sd = index_beginscan(irel, false, 1, &skey);
@@ -441,7 +426,7 @@ RelationBuildTriggers(Relation relation)
index_endscan(sd);
pfree(sd);
index_close(irel);
- heap_close(tgrel);
+ heap_close(tgrel, AccessShareLock);
/* Build trigdesc */
trigdesc->triggers = triggers;
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 1b0d972839..c05b6da585 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -5,7 +5,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: user.c,v 1.33 1999/07/30 18:09:47 momjian Exp $
+ * $Id: user.c,v 1.34 1999/09/18 19:06:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -36,13 +36,15 @@ static void CheckPgUserAclNotNull(void);
*
* copy the modified contents of pg_shadow to a file used by the postmaster
* for user authentication. The file is stored as $PGDATA/pg_pwd.
+ *
+ * NB: caller is responsible for ensuring that only one backend can
+ * execute this routine at a time. Acquiring AccessExclusiveLock on
+ * pg_shadow is the standard way to do that.
*---------------------------------------------------------------------
*/
-static
-void
+static void
UpdatePgPwdFile(char *sql, CommandDest dest)
{
-
char *filename,
*tempname;
int bufsize;
@@ -125,17 +127,13 @@ DefineUser(CreateUserStmt *stmt, CommandDest dest)
/*
* Scan the pg_shadow relation to be certain the user doesn't already
- * exist.
+ * exist. Note we secure exclusive lock, because we also need to be
+ * sure of what the next usesysid should be, and we need to protect
+ * our update of the flat password file.
*/
- pg_shadow_rel = heap_openr(ShadowRelationName);
+ pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock);
pg_shadow_dsc = RelationGetDescr(pg_shadow_rel);
- /*
- * Secure a write lock on pg_shadow so we can be sure of what the next
- * usesysid should be.
- */
- LockRelation(pg_shadow_rel, AccessExclusiveLock);
-
scan = heap_beginscan(pg_shadow_rel, false, SnapshotNow, 0, NULL);
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
{
@@ -152,8 +150,7 @@ DefineUser(CreateUserStmt *stmt, CommandDest dest)
if (exists)
{
- UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
- heap_close(pg_shadow_rel);
+ heap_close(pg_shadow_rel, AccessExclusiveLock);
UserAbortTransactionBlock();
elog(ERROR,
"defineUser: user \"%s\" has already been created", stmt->user);
@@ -165,6 +162,12 @@ DefineUser(CreateUserStmt *stmt, CommandDest dest)
*
* XXX Ugly as this code is, it still fails to cope with ' or \ in any of
* the provided strings.
+ *
+ * XXX This routine would be *lots* better if it inserted the new
+ * tuple with formtuple/heap_insert. For one thing, all of the
+ * transaction-block gamesmanship could be eliminated, because
+ * it's only there to make the world safe for a recursive call
+ * to pg_exec_query_dest().
*/
snprintf(sql, SQL_LENGTH,
"insert into %s (usename,usesysid,usecreatedb,usetrace,"
@@ -189,17 +192,21 @@ DefineUser(CreateUserStmt *stmt, CommandDest dest)
pg_exec_query_dest(sql, dest, false);
/*
- * Add the stuff here for groups.
+ * Add stuff here for groups?
*/
+ /*
+ * Write the updated pg_shadow data to the flat password file.
+ * Because we are still holding AccessExclusiveLock on pg_shadow,
+ * we can be sure no other backend will try to write the flat
+ * file at the same time.
+ */
UpdatePgPwdFile(sql, dest);
/*
- * This goes after the UpdatePgPwdFile to be certain that two backends
- * to not attempt to write to the pg_pwd file at the same time.
+ * Now we can clean up.
*/
- UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
- heap_close(pg_shadow_rel);
+ heap_close(pg_shadow_rel, AccessExclusiveLock);
if (IsTransactionBlock() && !inblock)
EndTransactionBlock();
@@ -237,70 +244,79 @@ AlterUser(AlterUserStmt *stmt, CommandDest dest)
/*
* Scan the pg_shadow relation to be certain the user exists.
+ * Note we secure exclusive lock to protect our update of the
+ * flat password file.
*/
- pg_shadow_rel = heap_openr(ShadowRelationName);
+ pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock);
pg_shadow_dsc = RelationGetDescr(pg_shadow_rel);
- /*
- * Secure a write lock on pg_shadow so we can be sure that when the
- * dump of the pg_pwd file is done, there is not another backend doing
- * the same.
- */
- LockRelation(pg_shadow_rel, AccessExclusiveLock);
-
tuple = SearchSysCacheTuple(USENAME,
PointerGetDatum(stmt->user),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
{
- UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
- heap_close(pg_shadow_rel);
- UserAbortTransactionBlock(); /* needed? */
+ heap_close(pg_shadow_rel, AccessExclusiveLock);
+ UserAbortTransactionBlock();
elog(ERROR, "alterUser: user \"%s\" does not exist", stmt->user);
- return;
}
/*
* Create the update statement to modify the user.
+ *
+ * XXX see diatribe in preceding routine. This code is just as bogus.
*/
snprintf(sql, SQL_LENGTH, "update %s set", ShadowRelationName);
if (stmt->password)
- snprintf(sql, SQL_LENGTH, "%s passwd = '%s'", pstrdup(sql), stmt->password);
+ snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql),
+ " passwd = '%s'", stmt->password);
if (stmt->createdb)
{
- snprintf(sql, SQL_LENGTH, "%s %susecreatedb='%s'",
- pstrdup(sql), stmt->password ? "," : "",
+ snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql),
+ "%s usecreatedb='%s'",
+ stmt->password ? "," : "",
*stmt->createdb ? "t" : "f");
}
if (stmt->createuser)
{
- snprintf(sql, SQL_LENGTH, "%s %susesuper='%s'",
- pstrdup(sql), (stmt->password || stmt->createdb) ? "," : "",
+ snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql),
+ "%s usesuper='%s'",
+ (stmt->password || stmt->createdb) ? "," : "",
*stmt->createuser ? "t" : "f");
}
if (stmt->validUntil)
{
- snprintf(sql, SQL_LENGTH, "%s %svaluntil='%s'",
- pstrdup(sql),
+ snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql),
+ "%s valuntil='%s'",
(stmt->password || stmt->createdb || stmt->createuser) ? "," : "",
stmt->validUntil);
}
- snprintf(sql, SQL_LENGTH, "%s where usename = '%s'",
- pstrdup(sql), stmt->user);
+ snprintf(sql + strlen(sql), SQL_LENGTH - strlen(sql),
+ " where usename = '%s'",
+ stmt->user);
pg_exec_query_dest(sql, dest, false);
- /* do the pg_group stuff here */
+ /*
+ * Add stuff here for groups?
+ */
+ /*
+ * Write the updated pg_shadow data to the flat password file.
+ * Because we are still holding AccessExclusiveLock on pg_shadow,
+ * we can be sure no other backend will try to write the flat
+ * file at the same time.
+ */
UpdatePgPwdFile(sql, dest);
- UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
- heap_close(pg_shadow_rel);
+ /*
+ * Now we can clean up.
+ */
+ heap_close(pg_shadow_rel, AccessExclusiveLock);
if (IsTransactionBlock() && !inblock)
EndTransactionBlock();
@@ -310,7 +326,6 @@ AlterUser(AlterUserStmt *stmt, CommandDest dest)
extern void
RemoveUser(char *user, CommandDest dest)
{
-
char *pg_shadow;
Relation pg_shadow_rel,
pg_rel;
@@ -318,7 +333,7 @@ RemoveUser(char *user, CommandDest dest)
HeapScanDesc scan;
HeapTuple tuple;
Datum datum;
- char sql[512];
+ char sql[SQL_LENGTH];
bool n,
inblock;
int32 usesysid;
@@ -341,27 +356,19 @@ RemoveUser(char *user, CommandDest dest)
}
/*
- * Perform a scan of the pg_shadow relation to find the usesysid of
- * the user to be deleted. If it is not found, then return a warning
- * message.
+ * Scan the pg_shadow relation to find the usesysid of the user to be
+ * deleted. Note we secure exclusive lock, because we need to protect
+ * our update of the flat password file.
*/
- pg_shadow_rel = heap_openr(ShadowRelationName);
+ pg_shadow_rel = heap_openr(ShadowRelationName, AccessExclusiveLock);
pg_dsc = RelationGetDescr(pg_shadow_rel);
- /*
- * Secure a write lock on pg_shadow so we can be sure that when the
- * dump of the pg_pwd file is done, there is not another backend doing
- * the same.
- */
- LockRelation(pg_shadow_rel, AccessExclusiveLock);
-
tuple = SearchSysCacheTuple(USENAME,
PointerGetDatum(user),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
{
- UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
- heap_close(pg_shadow_rel);
+ heap_close(pg_shadow_rel, AccessExclusiveLock);
UserAbortTransactionBlock();
elog(ERROR, "removeUser: user \"%s\" does not exist", user);
}
@@ -372,7 +379,7 @@ RemoveUser(char *user, CommandDest dest)
* Perform a scan of the pg_database relation to find the databases
* owned by usesysid. Then drop them.
*/
- pg_rel = heap_openr(DatabaseRelationName);
+ pg_rel = heap_openr(DatabaseRelationName, AccessExclusiveLock);
pg_dsc = RelationGetDescr(pg_rel);
scan = heap_beginscan(pg_rel, false, SnapshotNow, 0, NULL);
@@ -383,7 +390,7 @@ RemoveUser(char *user, CommandDest dest)
if ((int) datum == usesysid)
{
datum = heap_getattr(tuple, Anum_pg_database_datname, pg_dsc, &n);
- if (memcmp((void *) datum, "template1", 9))
+ if (memcmp((void *) datum, "template1", 9) != 0)
{
dbase =
(char **) repalloc((void *) dbase, sizeof(char *) * (ndbase + 1));
@@ -394,12 +401,12 @@ RemoveUser(char *user, CommandDest dest)
}
}
heap_endscan(scan);
- heap_close(pg_rel);
+ heap_close(pg_rel, AccessExclusiveLock);
while (ndbase--)
{
elog(NOTICE, "Dropping database %s", dbase[ndbase]);
- snprintf(sql, SQL_LENGTH, "drop database %s", dbase[ndbase]);
+ snprintf(sql, SQL_LENGTH, "DROP DATABASE %s", dbase[ndbase]);
pfree((void *) dbase[ndbase]);
pg_exec_query_dest(sql, dest, false);
}
@@ -431,10 +438,18 @@ RemoveUser(char *user, CommandDest dest)
"delete from %s where usename = '%s'", ShadowRelationName, user);
pg_exec_query_dest(sql, dest, false);
+ /*
+ * Write the updated pg_shadow data to the flat password file.
+ * Because we are still holding AccessExclusiveLock on pg_shadow,
+ * we can be sure no other backend will try to write the flat
+ * file at the same time.
+ */
UpdatePgPwdFile(sql, dest);
- UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
- heap_close(pg_shadow_rel);
+ /*
+ * Now we can clean up.
+ */
+ heap_close(pg_shadow_rel, AccessExclusiveLock);
if (IsTransactionBlock() && !inblock)
EndTransactionBlock();
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 55ec864fca..3027763b46 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.119 1999/08/25 12:20:57 ishii Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.120 1999/09/18 19:06:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -304,7 +304,7 @@ vc_getrels(NameData *VacRelP)
portalmem = PortalGetVariableMemory(vc_portal);
vrl = cur = (VRelList) NULL;
- rel = heap_openr(RelationRelationName);
+ rel = heap_openr(RelationRelationName, AccessShareLock);
tupdesc = RelationGetDescr(rel);
scan = heap_beginscan(rel, false, SnapshotNow, 1, &key);
@@ -343,9 +343,8 @@ vc_getrels(NameData *VacRelP)
if (found == false)
elog(NOTICE, "Vacuum: table not found");
-
heap_endscan(scan);
- heap_close(rel);
+ heap_close(rel, AccessShareLock);
CommitTransactionCommand();
@@ -395,8 +394,10 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
return;
}
- /* now open the class and vacuum it */
- onerel = heap_open(relid);
+ /*
+ * Open the class, get an exclusive lock on it, and vacuum it
+ */
+ onerel = heap_open(relid, AccessExclusiveLock);
vacrelstats = (VRelStats *) palloc(sizeof(VRelStats));
vacrelstats->relid = relid;
@@ -509,9 +510,6 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
vacrelstats->vacattrstats = (VacAttrStats *) NULL;
}
- /* we require the relation to be locked until the indices are cleaned */
- LockRelation(onerel, AccessExclusiveLock);
-
GetXmaxRecent(&XmaxRecent);
/* scan it */
@@ -565,13 +563,13 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
pfree(fraged_pages.vpl_pagedesc);
}
- /* all done with this class */
- heap_close(onerel);
-
/* update statistics in pg_class */
vc_updstats(vacrelstats->relid, vacrelstats->num_pages,
vacrelstats->num_tuples, vacrelstats->hasindex, vacrelstats);
+ /* all done with this class, but hold lock until commit */
+ heap_close(onerel, NoLock);
+
/* next command frees attribute stats */
CommitTransactionCommand();
}
@@ -2281,6 +2279,8 @@ vc_updstats(Oid relid, int num_pages, int num_tuples, bool hasindex, VRelStats *
/*
* update number of tuples and number of pages in pg_class
*/
+ rd = heap_openr(RelationRelationName, RowExclusiveLock);
+
ctup = SearchSysCacheTupleCopy(RELOID,
ObjectIdGetDatum(relid),
0, 0, 0);
@@ -2288,8 +2288,6 @@ vc_updstats(Oid relid, int num_pages, int num_tuples, bool hasindex, VRelStats *
elog(ERROR, "pg_class entry for relid %u vanished during vacuuming",
relid);
- rd = heap_openr(RelationRelationName);
-
/* get the buffer cache tuple */
rtup.t_self = ctup->t_self;
heap_fetch(rd, SnapshotNow, &rtup, &buffer);
@@ -2306,8 +2304,8 @@ vc_updstats(Oid relid, int num_pages, int num_tuples, bool hasindex, VRelStats *
VacAttrStats *vacattrstats = vacrelstats->vacattrstats;
int natts = vacrelstats->va_natts;
- ad = heap_openr(AttributeRelationName);
- sd = heap_openr(StatisticRelationName);
+ ad = heap_openr(AttributeRelationName, RowExclusiveLock);
+ sd = heap_openr(StatisticRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&askey, 0, Anum_pg_attribute_attrelid,
F_INT4EQ, relid);
@@ -2458,8 +2456,8 @@ vc_updstats(Oid relid, int num_pages, int num_tuples, bool hasindex, VRelStats *
}
}
heap_endscan(scan);
- heap_close(ad);
- heap_close(sd);
+ heap_close(ad, RowExclusiveLock);
+ heap_close(sd, RowExclusiveLock);
}
/*
@@ -2469,7 +2467,7 @@ vc_updstats(Oid relid, int num_pages, int num_tuples, bool hasindex, VRelStats *
WriteBuffer(buffer);
- heap_close(rd);
+ heap_close(rd, RowExclusiveLock);
}
/*
@@ -2484,7 +2482,7 @@ vc_delhilowstats(Oid relid, int attcnt, int *attnums)
HeapTuple tuple;
ScanKeyData key;
- pgstatistic = heap_openr(StatisticRelationName);
+ pgstatistic = heap_openr(StatisticRelationName, RowExclusiveLock);
if (relid != InvalidOid)
{
@@ -2515,7 +2513,7 @@ vc_delhilowstats(Oid relid, int attcnt, int *attnums)
}
heap_endscan(scan);
- heap_close(pgstatistic);
+ heap_close(pgstatistic, RowExclusiveLock);
}
/*
@@ -2721,7 +2719,7 @@ vc_getindices(Oid relid, int *nindices, Relation **Irel)
ioid = (Oid *) palloc(10 * sizeof(Oid));
/* prepare a heap scan on the pg_index relation */
- pgindex = heap_openr(IndexRelationName);
+ pgindex = heap_openr(IndexRelationName, AccessShareLock);
tupdesc = RelationGetDescr(pgindex);
ScanKeyEntryInitialize(&key, 0x0, Anum_pg_index_indrelid,
@@ -2741,7 +2739,7 @@ vc_getindices(Oid relid, int *nindices, Relation **Irel)
}
heap_endscan(scan);
- heap_close(pgindex);
+ heap_close(pgindex, AccessShareLock);
if (i == 0)
{ /* No one index found */