diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index ad954605373b25b2ca82ab96d6ca910f6204d0df..7ae852672c5028aed87db2f22e581a35ff5e53bc 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.30 2003/02/03 21:15:43 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.31 2003/02/19 04:02:53 momjian Exp $
  *
  * DESCRIPTION
  *	  The "DefineFoo" routines take the parse tree and pick out the
@@ -353,6 +353,12 @@ RemoveType(List *names, DropBehavior behavior)
 		elog(ERROR, "Type \"%s\" does not exist",
 			 TypeNameToString(typename));
 
+	/*
+	 * Grab an exclusive lock on the type id, the SearchSysCache confirms
+	 * the type still exists after locking
+	 */
+	LockObject(typeoid, RelOid_pg_type, AccessExclusiveLock);
+
 	tup = SearchSysCache(TYPEOID,
 						 ObjectIdGetDatum(typeoid),
 						 0, 0, 0);
@@ -376,6 +382,9 @@ RemoveType(List *names, DropBehavior behavior)
 	object.objectSubId = 0;
 
 	performDeletion(&object, behavior);
+
+	/* Hold the lock until the end of the transaction */
+	UnlockObject(typeoid, RelOid_pg_type, NoLock);
 }
 
 
@@ -680,7 +689,7 @@ void
 RemoveDomain(List *names, DropBehavior behavior)
 {
 	TypeName   *typename;
-	Oid			typeoid;
+	Oid			domainoid;
 	HeapTuple	tup;
 	char		typtype;
 	ObjectAddress object;
@@ -692,20 +701,26 @@ RemoveDomain(List *names, DropBehavior behavior)
 	typename->arrayBounds = NIL;
 
 	/* Use LookupTypeName here so that shell types can be removed. */
-	typeoid = LookupTypeName(typename);
-	if (!OidIsValid(typeoid))
+	domainoid = LookupTypeName(typename);
+	if (!OidIsValid(domainoid))
 		elog(ERROR, "Type \"%s\" does not exist",
 			 TypeNameToString(typename));
 
+	/*
+	 * Lock the domain.  The SearchSysCache confirms the domain still exists
+	 * after locking
+	 */
+	LockObject(domainoid, RelOid_pg_type, AccessExclusiveLock);
+
 	tup = SearchSysCache(TYPEOID,
-						 ObjectIdGetDatum(typeoid),
+						 ObjectIdGetDatum(domainoid),
 						 0, 0, 0);
 	if (!HeapTupleIsValid(tup))
 		elog(ERROR, "RemoveDomain: type \"%s\" does not exist",
 			 TypeNameToString(typename));
 
 	/* Permission check: must own type or its namespace */
-	if (!pg_type_ownercheck(typeoid, GetUserId()) &&
+	if (!pg_type_ownercheck(domainoid, GetUserId()) &&
 		!pg_namespace_ownercheck(((Form_pg_type) GETSTRUCT(tup))->typnamespace,
 								 GetUserId()))
 		aclcheck_error(ACLCHECK_NOT_OWNER, TypeNameToString(typename));
@@ -723,10 +738,13 @@ RemoveDomain(List *names, DropBehavior behavior)
 	 * Do the deletion
 	 */
 	object.classId = RelOid_pg_type;
-	object.objectId = typeoid;
+	object.objectId = domainoid;
 	object.objectSubId = 0;
 
 	performDeletion(&object, behavior);
+
+	/* Hold the lock until the end of the transaction */
+	UnlockObject(domainoid, RelOid_pg_type, NoLock);
 }
 
 
@@ -941,6 +959,12 @@ AlterDomainDefault(List *names, Node *defaultRaw)
 		elog(ERROR, "Type \"%s\" does not exist",
 			 TypeNameToString(typename));
 
+	/*
+	 * Lock the domain.  The SearchSysCacheCopy confirms the type
+	 * still exists after locking
+	 */
+	LockObject(domainoid, RelOid_pg_type, AccessExclusiveLock);
+
 	tup = SearchSysCacheCopy(TYPEOID,
 							 ObjectIdGetDatum(domainoid),
 							 0, 0, 0);
@@ -1025,6 +1049,7 @@ AlterDomainDefault(List *names, Node *defaultRaw)
 	/* Clean up */
 	heap_close(rel, NoLock);
 	heap_freetuple(newtuple);
+	UnlockObject(domainoid, RelOid_pg_type, NoLock);
 };
 
 /*
@@ -1056,6 +1081,12 @@ AlterDomainNotNull(List *names, bool notNull)
 		elog(ERROR, "Type \"%s\" does not exist",
 			 TypeNameToString(typename));
 
+	/*
+	 * Lock the domain.  The SearchSysCacheCopy confirms the domain
+	 * still exists after locking
+	 */
+	LockObject(domainoid, RelOid_pg_type, AccessExclusiveLock);
+
 	tup = SearchSysCacheCopy(TYPEOID,
 							 ObjectIdGetDatum(domainoid),
 							 0, 0, 0);
@@ -1137,6 +1168,7 @@ AlterDomainNotNull(List *names, bool notNull)
 	/* Clean up */
 	heap_freetuple(tup);
 	heap_close(typrel, RowExclusiveLock);
+	UnlockObject(domainoid, RelOid_pg_type, NoLock);
 }
 
 /*
@@ -1172,6 +1204,12 @@ AlterDomainDropConstraint(List *names, const char *constrName, DropBehavior beha
 		elog(ERROR, "Type \"%s\" does not exist",
 			 TypeNameToString(typename));
 
+	/*
+	 * Lock the domain.  The SearchSysCacheCopy confirms the type still
+	 * exists after locking.
+	 */
+	LockObject(domainoid, RelOid_pg_type, AccessExclusiveLock);
+
 	tup = SearchSysCacheCopy(TYPEOID,
 							 ObjectIdGetDatum(domainoid),
 							 0, 0, 0);
@@ -1219,6 +1257,7 @@ AlterDomainDropConstraint(List *names, const char *constrName, DropBehavior beha
 	heap_close(conrel, RowExclusiveLock);
 
 	heap_close(rel, NoLock);
+	UnlockObject(domainoid, RelOid_pg_type, NoLock);
 };
 
 /*
@@ -1259,6 +1298,12 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
 		elog(ERROR, "Type \"%s\" does not exist",
 			 TypeNameToString(typename));
 
+	/*
+	 * Lock the domain.  The SearchSysCacheCopy confirms the domain
+	 * still exists after locking.
+	 */
+	LockObject(domainoid, RelOid_pg_type, AccessExclusiveLock);
+
 	tup = SearchSysCacheCopy(TYPEOID,
 							 ObjectIdGetDatum(domainoid),
 							 0, 0, 0);
@@ -1393,6 +1438,7 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
 
 	/* Clean up */
 	heap_close(typrel, RowExclusiveLock);
+	UnlockObject(domainoid, RelOid_pg_type, NoLock);
 }
 
 /*
@@ -1696,7 +1742,10 @@ GetDomainConstraints(Oid typeOid)
 		Form_pg_type typTup;
 		ScanKeyData key[1];
 		SysScanDesc scan;
-		
+
+		/* Lock the domain */
+		LockObject(typeOid, RelOid_pg_type, AccessShareLock);
+
 		tup = SearchSysCache(TYPEOID,
 							 ObjectIdGetDatum(typeOid),
 							 0, 0, 0);
@@ -1824,6 +1873,12 @@ AlterTypeOwner(List *names, AclId newOwnerSysId)
 		elog(ERROR, "Type \"%s\" does not exist",
 			 TypeNameToString(typename));
 
+	/*
+	 * Lock the type.  The SearchSysCacheCopy serves to confirm the
+	 * domain still exists after locking
+	 */
+	LockObject(typeOid, RelOid_pg_type, AccessExclusiveLock);
+
 	tup = SearchSysCacheCopy(TYPEOID,
 							 ObjectIdGetDatum(typeOid),
 							 0, 0, 0);
@@ -1846,4 +1901,5 @@ AlterTypeOwner(List *names, AclId newOwnerSysId)
 
 	/* Clean up */
 	heap_close(rel, RowExclusiveLock);
+	UnlockObject(typeOid, RelOid_pg_type, NoLock);
 }
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
index 8f7c34cbd3d7ddafcafeacad11f5c99fa2152370..56379a28119cb6ef7633ed06030bae963913f4bc 100644
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.51 2003/02/09 06:56:28 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.52 2003/02/19 04:02:53 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,6 +23,7 @@
 #include "parser/parser.h"
 #include "parser/parse_expr.h"
 #include "parser/parse_type.h"
+#include "storage/lmgr.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
@@ -127,6 +128,15 @@ LookupTypeName(const TypeName *typename)
 		}
 	}
 
+	/*
+	 * Lock the type as having been read for remainder of the transaction
+	 *
+	 * XXX: There is a small time between the above and now when the type
+	 *		could dissapear.  We *should* recheck to confirm the type still
+	 *		exists, but won't for speed.
+	 */
+	LockObject(restype, RelOid_pg_type, AccessShareLock);
+
 	return restype;
 }
 
diff --git a/src/backend/storage/lmgr/deadlock.c b/src/backend/storage/lmgr/deadlock.c
index 61ab1962fb697bfe6b644115e6be192000aa75c9..9191d40b1e7a95b652dd90ff6782a7809b693a48 100644
--- a/src/backend/storage/lmgr/deadlock.c
+++ b/src/backend/storage/lmgr/deadlock.c
@@ -12,7 +12,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/deadlock.c,v 1.17 2003/02/18 02:13:24 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/deadlock.c,v 1.18 2003/02/19 04:02:53 momjian Exp $
  *
  *	Interface:
  *
@@ -855,22 +855,25 @@ DeadLockReport(void)
 		else
 			nextpid = deadlockDetails[0].pid;
 
-		if (info->locktag.relId == XactLockTableId && info->locktag.dbId == 0)
+		if (info->locktag.objId == InvalidOid
+			&& info->locktag.classId == XactLockTableId
+			&& info->locktag.dbId == InvalidOid)
 		{
 			/* Lock is for transaction ID */
 			elog(NOTICE, "Proc %d waits for %s on transaction %u; blocked by %d",
 				 info->pid,
 				 GetLockmodeName(info->lockmode),
-				 info->locktag.objId.xid,
+				 info->locktag.objsubId.xid,
 				 nextpid);
 		}
 		else
 		{
 			/* Lock is for a relation */
-			elog(NOTICE, "Proc %d waits for %s on relation %u database %u; blocked by %d",
+			elog(NOTICE, "Proc %d waits for %s on object %u class %u database %u; blocked by %d",
 				 info->pid,
 				 GetLockmodeName(info->lockmode),
-				 info->locktag.relId,
+				 info->locktag.objId,
+				 info->locktag.classId,
 				 info->locktag.dbId,
 				 nextpid);
 		}
diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c
index a4e9197edc72a2fe00983f69baa1f5e833ef3166..a1011054fa3672c1b346f749dadea1e98ce7731b 100644
--- a/src/backend/storage/lmgr/lmgr.c
+++ b/src/backend/storage/lmgr/lmgr.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.54 2002/08/01 05:18:33 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.55 2003/02/19 04:02:53 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -126,9 +126,10 @@ LockRelation(Relation relation, LOCKMODE lockmode)
 	LOCKTAG		tag;
 
 	MemSet(&tag, 0, sizeof(tag));
-	tag.relId = relation->rd_lockInfo.lockRelId.relId;
+	tag.objId = relation->rd_lockInfo.lockRelId.relId;
+	tag.classId = RelOid_pg_class;
 	tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
-	tag.objId.blkno = InvalidBlockNumber;
+	tag.objsubId.blkno = InvalidBlockNumber;
 
 	if (!LockAcquire(LockTableId, &tag, GetCurrentTransactionId(),
 					 lockmode, false))
@@ -160,9 +161,10 @@ ConditionalLockRelation(Relation relation, LOCKMODE lockmode)
 	LOCKTAG		tag;
 
 	MemSet(&tag, 0, sizeof(tag));
-	tag.relId = relation->rd_lockInfo.lockRelId.relId;
+	tag.objId = relation->rd_lockInfo.lockRelId.relId;
+	tag.classId = RelOid_pg_class;
 	tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
-	tag.objId.blkno = InvalidBlockNumber;
+	tag.objsubId.blkno = InvalidBlockNumber;
 
 	if (!LockAcquire(LockTableId, &tag, GetCurrentTransactionId(),
 					 lockmode, true))
@@ -190,9 +192,10 @@ UnlockRelation(Relation relation, LOCKMODE lockmode)
 	LOCKTAG		tag;
 
 	MemSet(&tag, 0, sizeof(tag));
-	tag.relId = relation->rd_lockInfo.lockRelId.relId;
+	tag.objId = relation->rd_lockInfo.lockRelId.relId;
+	tag.classId = RelOid_pg_class;
 	tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
-	tag.objId.blkno = InvalidBlockNumber;
+	tag.objsubId.blkno = InvalidBlockNumber;
 
 	LockRelease(LockTableId, &tag, GetCurrentTransactionId(), lockmode);
 }
@@ -215,9 +218,10 @@ LockRelationForSession(LockRelId *relid, LOCKMODE lockmode)
 	LOCKTAG		tag;
 
 	MemSet(&tag, 0, sizeof(tag));
-	tag.relId = relid->relId;
+	tag.objId = relid->relId;
+	tag.classId = RelOid_pg_class;
 	tag.dbId = relid->dbId;
-	tag.objId.blkno = InvalidBlockNumber;
+	tag.objsubId.blkno = InvalidBlockNumber;
 
 	if (!LockAcquire(LockTableId, &tag, InvalidTransactionId,
 					 lockmode, false))
@@ -233,9 +237,10 @@ UnlockRelationForSession(LockRelId *relid, LOCKMODE lockmode)
 	LOCKTAG		tag;
 
 	MemSet(&tag, 0, sizeof(tag));
-	tag.relId = relid->relId;
+	tag.objId = relid->relId;
+	tag.classId = RelOid_pg_class;
 	tag.dbId = relid->dbId;
-	tag.objId.blkno = InvalidBlockNumber;
+	tag.objsubId.blkno = InvalidBlockNumber;
 
 	LockRelease(LockTableId, &tag, InvalidTransactionId, lockmode);
 }
@@ -253,9 +258,10 @@ LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
 	LOCKTAG		tag;
 
 	MemSet(&tag, 0, sizeof(tag));
-	tag.relId = relation->rd_lockInfo.lockRelId.relId;
+	tag.objId = relation->rd_lockInfo.lockRelId.relId;
+	tag.classId = RelOid_pg_class;
 	tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
-	tag.objId.blkno = blkno;
+	tag.objsubId.blkno = blkno;
 
 	if (!LockAcquire(LockTableId, &tag, GetCurrentTransactionId(),
 					 lockmode, false))
@@ -271,9 +277,10 @@ UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
 	LOCKTAG		tag;
 
 	MemSet(&tag, 0, sizeof(tag));
-	tag.relId = relation->rd_lockInfo.lockRelId.relId;
+	tag.objId = relation->rd_lockInfo.lockRelId.relId;
+	tag.classId = RelOid_pg_class;
 	tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
-	tag.objId.blkno = blkno;
+	tag.objsubId.blkno = blkno;
 
 	LockRelease(LockTableId, &tag, GetCurrentTransactionId(), lockmode);
 }
@@ -294,9 +301,10 @@ XactLockTableInsert(TransactionId xid)
 	LOCKTAG		tag;
 
 	MemSet(&tag, 0, sizeof(tag));
-	tag.relId = XactLockTableId;
+	tag.objId = InvalidOid;
+	tag.classId = XactLockTableId;
 	tag.dbId = InvalidOid;		/* xids are globally unique */
-	tag.objId.xid = xid;
+	tag.objsubId.xid = xid;
 
 	if (!LockAcquire(LockTableId, &tag, xid,
 					 ExclusiveLock, false))
@@ -317,9 +325,10 @@ XactLockTableWait(TransactionId xid)
 	Assert(!TransactionIdEquals(xid, myxid));
 
 	MemSet(&tag, 0, sizeof(tag));
-	tag.relId = XactLockTableId;
+	tag.objId = InvalidOid;
+	tag.classId = XactLockTableId;
 	tag.dbId = InvalidOid;
-	tag.objId.xid = xid;
+	tag.objsubId.xid = xid;
 
 	if (!LockAcquire(LockTableId, &tag, myxid,
 					 ShareLock, false))
@@ -334,3 +343,59 @@ XactLockTableWait(TransactionId xid)
 	if (!TransactionIdDidCommit(xid) && !TransactionIdDidAbort(xid))
 		TransactionIdAbort(xid);
 }
+
+/*
+ * LockObject
+ *
+ * Lock an arbitrary database object.  A standard relation lock would lock the
+ * classId of RelOid_pg_class and objId of the relations OID within the pg_class
+ * table.  LockObject allows classId to be specified by the caller, thus allowing
+ * locks on any row in any system table.
+ *
+ * If classId is NOT a system table (protected from removal), an additional lock
+ * should be held on the relation to prevent it from being dropped.
+ */
+void
+LockObject(Oid objId, Oid classId, LOCKMODE lockmode)
+{
+	LOCKTAG		tag;
+
+	MemSet(&tag, 0, sizeof(tag));
+	tag.objId = objId;
+	tag.classId = classId;
+	tag.dbId = MyDatabaseId;
+	tag.objsubId.blkno = InvalidBlockNumber;
+
+	/* Only two reasonable lock types */
+	Assert(lockmode == AccessShareLock || lockmode == AccessExclusiveLock);
+
+	if (!LockAcquire(LockTableId, &tag, GetCurrentTransactionId(),
+					 lockmode, false))
+		elog(ERROR, "LockObject: LockAcquire failed");
+}
+
+/*
+ * UnlockObject
+ */
+void
+UnlockObject(Oid objId, Oid classId, LOCKMODE lockmode)
+{
+	LOCKTAG		tag;
+
+	/* NoLock is a no-op */
+	if (lockmode == NoLock)
+		return;
+
+	MemSet(&tag, 0, sizeof(tag));
+	tag.objId = objId;
+	tag.classId = classId;
+	tag.dbId = MyDatabaseId;
+	tag.objsubId.blkno = InvalidBlockNumber;
+
+	/* Only two reasonable lock types */
+	Assert(lockmode == AccessShareLock
+		  || lockmode == AccessExclusiveLock);
+
+	LockRelease(LockTableId, &tag, GetCurrentTransactionId(), lockmode);
+}
+
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index d0c5a055f9e0d24a144eb547cdd69c1392bc954b..959fe7877a05e4e618256d7813784ce218ac2398 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.120 2003/02/18 02:13:24 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.121 2003/02/19 04:02:53 momjian Exp $
  *
  * NOTES
  *	  Outside modules can create a lock table and acquire/release
@@ -97,8 +97,8 @@ LOCK_DEBUG_ENABLED(const LOCK *lock)
 	return
 		(((LOCK_LOCKMETHOD(*lock) == DEFAULT_LOCKMETHOD && Trace_locks)
 	   || (LOCK_LOCKMETHOD(*lock) == USER_LOCKMETHOD && Trace_userlocks))
-		 && (lock->tag.relId >= (Oid) Trace_lock_oidmin))
-		|| (Trace_lock_table && (lock->tag.relId == Trace_lock_table));
+		 && (lock->tag.objId >= (Oid) Trace_lock_oidmin))
+		|| (Trace_lock_table && (lock->tag.objId == Trace_lock_table));
 }
 
 
@@ -107,12 +107,12 @@ LOCK_PRINT(const char *where, const LOCK *lock, LOCKMODE type)
 {
 	if (LOCK_DEBUG_ENABLED(lock))
 		elog(LOG,
-			 "%s: lock(%lx) tbl(%d) rel(%u) db(%u) obj(%u) grantMask(%x) "
+			 "%s: lock(%lx) tbl(%d) obj(%u) class(%u) db(%u) objsub(%u) grantMask(%x) "
 			 "req(%d,%d,%d,%d,%d,%d,%d)=%d "
 			 "grant(%d,%d,%d,%d,%d,%d,%d)=%d wait(%d) type(%s)",
 			 where, MAKE_OFFSET(lock),
-			 lock->tag.lockmethod, lock->tag.relId, lock->tag.dbId,
-			 lock->tag.objId.blkno, lock->grantMask,
+			 lock->tag.lockmethod, lock->tag.objId, lock->tag.classId, lock->tag.dbId,
+			 lock->tag.objsubId.blkno, lock->grantMask,
 			 lock->requested[1], lock->requested[2], lock->requested[3],
 			 lock->requested[4], lock->requested[5], lock->requested[6],
 			 lock->requested[7], lock->nRequested,
@@ -129,16 +129,16 @@ PROCLOCK_PRINT(const char *where, const PROCLOCK *proclockP)
 	if (
 	(((PROCLOCK_LOCKMETHOD(*proclockP) == DEFAULT_LOCKMETHOD && Trace_locks)
 	  || (PROCLOCK_LOCKMETHOD(*proclockP) == USER_LOCKMETHOD && Trace_userlocks))
-	 && (((LOCK *) MAKE_PTR(proclockP->tag.lock))->tag.relId >= (Oid) Trace_lock_oidmin))
-		|| (Trace_lock_table && (((LOCK *) MAKE_PTR(proclockP->tag.lock))->tag.relId == Trace_lock_table))
+	 && (((LOCK *) MAKE_PTR(proclockP->tag.lock))->tag.objId >= (Oid) Trace_lock_oidmin))
+		|| (Trace_lock_table && (((LOCK *) MAKE_PTR(proclockP->tag.lock))->tag.objId == Trace_lock_table))
 		)
 		elog(LOG,
 			 "%s: proclock(%lx) lock(%lx) tbl(%d) proc(%lx) xid(%u) hold(%d,%d,%d,%d,%d,%d,%d)=%d",
 			 where, MAKE_OFFSET(proclockP), proclockP->tag.lock,
 			 PROCLOCK_LOCKMETHOD(*(proclockP)),
 			 proclockP->tag.proc, proclockP->tag.xid,
-		   proclockP->holding[1], proclockP->holding[2], proclockP->holding[3],
-		   proclockP->holding[4], proclockP->holding[5], proclockP->holding[6],
+			 proclockP->holding[1], proclockP->holding[2], proclockP->holding[3],
+			 proclockP->holding[4], proclockP->holding[5], proclockP->holding[6],
 			 proclockP->holding[7], proclockP->nHolding);
 }
 
@@ -417,8 +417,9 @@ LockMethodTableRename(LOCKMETHOD lockmethod)
  *
  *		lockmethod						1				2
  *		tag.dbId						database oid	database oid
- *		tag.relId						rel oid or 0	0
- *		tag.objId						block id		lock id2
+ *		tag.classId						class oid		0
+ *		tag.objId						rel oid or 0	0
+ *		tag.objsubId					block id		lock id2
  *										or xact id
  *		tag.offnum						0				lock id1
  *		proclock.xid					xid or 0		0
@@ -449,7 +450,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 #ifdef LOCK_DEBUG
 	if (lockmethod == USER_LOCKMETHOD && Trace_userlocks)
 		elog(LOG, "LockAcquire: user lock [%u] %s",
-			 locktag->objId.blkno, lock_mode_names[lockmode]);
+			 locktag->objsubId.blkno, lock_mode_names[lockmode]);
 #endif
 
 	/* ???????? This must be changed when short term locks will be used */
@@ -572,7 +573,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 				elog(LOG, "Deadlock risk: raising lock level"
 					 " from %s to %s on object %u/%u/%u",
 					 lock_mode_names[i], lock_mode_names[lockmode],
-				 lock->tag.relId, lock->tag.dbId, lock->tag.objId.blkno);
+				 lock->tag.objId, lock->tag.dbId, lock->tag.objsubId.blkno);
 				break;
 			}
 		}
@@ -993,7 +994,7 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 
 #ifdef LOCK_DEBUG
 	if (lockmethod == USER_LOCKMETHOD && Trace_userlocks)
-		elog(LOG, "LockRelease: user lock tag [%u] %d", locktag->objId.blkno, lockmode);
+		elog(LOG, "LockRelease: user lock tag [%u] %d", locktag->objsubId.blkno, lockmode);
 #endif
 
 	/* ???????? This must be changed when short term locks will be used */
diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c
index 37788d8ff0d847b9bd51f8f66d0e3d18dbd85f78..25bc726cba2389a2c3d5986138a3cd2c2bc21e4f 100644
--- a/src/backend/utils/adt/lockfuncs.c
+++ b/src/backend/utils/adt/lockfuncs.c
@@ -6,7 +6,7 @@
  * Copyright (c) 2002, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *		$Header: /cvsroot/pgsql/src/backend/utils/adt/lockfuncs.c,v 1.8 2003/02/18 02:13:24 momjian Exp $
+ *		$Header: /cvsroot/pgsql/src/backend/utils/adt/lockfuncs.c,v 1.9 2003/02/19 04:02:54 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,18 +53,20 @@ pg_lock_status(PG_FUNCTION_ARGS)
 
 		/* build tupdesc for result tuples */
 		/* this had better match pg_locks view in initdb.sh */
-		tupdesc = CreateTemplateTupleDesc(6, false);
-		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "relation",
+		tupdesc = CreateTemplateTupleDesc(7, false);
+		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "object",
 						   OIDOID, -1, 0, false);
-		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "database",
+		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "class",
 						   OIDOID, -1, 0, false);
-		TupleDescInitEntry(tupdesc, (AttrNumber) 3, "transaction",
+		TupleDescInitEntry(tupdesc, (AttrNumber) 3, "database",
+						   OIDOID, -1, 0, false);
+		TupleDescInitEntry(tupdesc, (AttrNumber) 4, "transaction",
 						   XIDOID, -1, 0, false);
-		TupleDescInitEntry(tupdesc, (AttrNumber) 4, "pid",
+		TupleDescInitEntry(tupdesc, (AttrNumber) 5, "pid",
 						   INT4OID, -1, 0, false);
-		TupleDescInitEntry(tupdesc, (AttrNumber) 5, "mode",
+		TupleDescInitEntry(tupdesc, (AttrNumber) 6, "mode",
 						   TEXTOID, -1, 0, false);
-		TupleDescInitEntry(tupdesc, (AttrNumber) 6, "granted",
+		TupleDescInitEntry(tupdesc, (AttrNumber) 7, "granted",
 						   BOOLOID, -1, 0, false);
 
 		funcctx->slot = TupleDescGetSlot(tupdesc);
@@ -93,8 +95,8 @@ pg_lock_status(PG_FUNCTION_ARGS)
 		PGPROC	   *proc;
 		bool		granted;
 		LOCKMODE	mode;
-		Datum		values[6];
-		char		nulls[6];
+		Datum		values[7];
+		char		nulls[7];
 		HeapTuple	tuple;
 		Datum		result;
 
@@ -152,26 +154,30 @@ pg_lock_status(PG_FUNCTION_ARGS)
 		MemSet(values, 0, sizeof(values));
 		MemSet(nulls, ' ', sizeof(nulls));
 
-		if (lock->tag.relId == XactLockTableId && lock->tag.dbId == 0)
+		if (lock->tag.objId == InvalidOid
+			&& lock->tag.classId == XactLockTableId
+			&& lock->tag.dbId == InvalidOid)
 		{
 			/* Lock is for transaction ID */
 			nulls[0] = 'n';
 			nulls[1] = 'n';
-			values[2] = TransactionIdGetDatum(lock->tag.objId.xid);
+			nulls[2] = 'n';
+			values[3] = TransactionIdGetDatum(lock->tag.objsubId.xid);
 		}
 		else
 		{
 			/* Lock is for a relation */
-			values[0] = ObjectIdGetDatum(lock->tag.relId);
-			values[1] = ObjectIdGetDatum(lock->tag.dbId);
-			nulls[2] = 'n';
+			values[0] = ObjectIdGetDatum(lock->tag.objId);
+			values[1] = ObjectIdGetDatum(lock->tag.classId);
+			values[2] = ObjectIdGetDatum(lock->tag.dbId);
+			nulls[3] = 'n';
 
 		}
 
-		values[3] = Int32GetDatum(proc->pid);
-		values[4] = DirectFunctionCall1(textin,
+		values[4] = Int32GetDatum(proc->pid);
+		values[5] = DirectFunctionCall1(textin,
 								 CStringGetDatum(GetLockmodeName(mode)));
-		values[5] = BoolGetDatum(granted);
+		values[6] = BoolGetDatum(granted);
 
 		tuple = heap_formtuple(funcctx->slot->ttc_tupleDescriptor,
 							   values, nulls);
diff --git a/src/bin/initdb/initdb.sh b/src/bin/initdb/initdb.sh
index 5dad4e34a05031ee64cfad015001f063459d9274..b75e8c2a48a4db2b931e3a55e1ce4832ec37fb18 100644
--- a/src/bin/initdb/initdb.sh
+++ b/src/bin/initdb/initdb.sh
@@ -27,7 +27,7 @@
 # Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
 # Portions Copyright (c) 1994, Regents of the University of California
 #
-# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.182 2003/01/23 23:39:01 petere Exp $
+# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.183 2003/02/19 04:02:54 momjian Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -974,7 +974,7 @@ CREATE VIEW pg_stat_database AS \
 
 CREATE VIEW pg_locks AS \
     SELECT * \
-    FROM pg_lock_status() AS L(relation oid, database oid, \
+    FROM pg_lock_status() AS L(object oid, class oid, database oid, \
 	transaction xid, pid int4, mode text, granted boolean);
 
 CREATE VIEW pg_settings AS \
diff --git a/src/include/storage/lmgr.h b/src/include/storage/lmgr.h
index 8437e104f4ae6b059aec4325aff62d56a154647a..17b095b274b8c39f7774b47a6ff057eb3437101b 100644
--- a/src/include/storage/lmgr.h
+++ b/src/include/storage/lmgr.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: lmgr.h,v 1.36 2002/06/20 20:29:52 momjian Exp $
+ * $Id: lmgr.h,v 1.37 2003/02/19 04:02:54 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -62,4 +62,8 @@ extern void UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode);
 extern void XactLockTableInsert(TransactionId xid);
 extern void XactLockTableWait(TransactionId xid);
 
+/* Lock an arbitrary database object in the current database */
+extern void LockObject(Oid objId, Oid classId, LOCKMODE lockmode);
+extern void UnlockObject(Oid objId, Oid classId, LOCKMODE lockmode);
+
 #endif   /* LMGR_H */
diff --git a/src/include/storage/lock.h b/src/include/storage/lock.h
index f31dc1d9b8803ff219a6a438b80f1c5bc254bc01..fb40a5d104046f42639897713b622752897b3584 100644
--- a/src/include/storage/lock.h
+++ b/src/include/storage/lock.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: lock.h,v 1.69 2003/02/18 02:13:24 momjian Exp $
+ * $Id: lock.h,v 1.70 2003/02/19 04:02:54 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -100,13 +100,14 @@ typedef struct LOCKMETHODTABLE
  */
 typedef struct LOCKTAG
 {
-	Oid			relId;
+	Oid			objId;
+	Oid			classId;
 	Oid			dbId;
 	union
 	{
 		BlockNumber blkno;
 		TransactionId xid;
-	}			objId;
+	}			objsubId;
 
 	/*
 	 * offnum should be part of objId.tupleId above, but would increase
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index f302ad93138dd534887fa255f0683584b45faba1..12bfccc0173d4c610a0bd7e6c3331f44bbc06caa 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1271,7 +1271,7 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem
 --------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  iexit                    | SELECT ih.name, ih.thepath, interpt_pp(ih.thepath, r.thepath) AS exit FROM ihighway ih, ramp r WHERE (ih.thepath ## r.thepath);
  pg_indexes               | SELECT n.nspname AS schemaname, c.relname AS tablename, i.relname AS indexname, pg_get_indexdef(i.oid) AS indexdef FROM (((pg_index x JOIN pg_class c ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE ((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char"));
- pg_locks                 | SELECT l.relation, l."database", l."transaction", l.pid, l."mode", l.granted FROM pg_lock_status() l(relation oid, "database" oid, "transaction" xid, pid integer, "mode" text, granted boolean);
+ pg_locks                 | SELECT l.object, l."class", l."database", l."transaction", l.pid, l."mode", l.granted FROM pg_lock_status() l(object oid, "class" oid, "database" oid, "transaction" xid, pid integer, "mode" text, granted boolean);
  pg_rules                 | SELECT n.nspname AS schemaname, c.relname AS tablename, r.rulename, pg_get_ruledef(r.oid) AS definition FROM ((pg_rewrite r JOIN pg_class c ON ((c.oid = r.ev_class))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (r.rulename <> '_RETURN'::name);
  pg_settings              | SELECT a.name, a.setting FROM pg_show_all_settings() a(name text, setting text);
  pg_stat_activity         | SELECT d.oid AS datid, d.datname, pg_stat_get_backend_pid(s.backendid) AS procpid, pg_stat_get_backend_userid(s.backendid) AS usesysid, u.usename, pg_stat_get_backend_activity(s.backendid) AS current_query FROM pg_database d, (SELECT pg_stat_get_backend_idset() AS backendid) s, pg_shadow u WHERE ((pg_stat_get_backend_dbid(s.backendid) = d.oid) AND (pg_stat_get_backend_userid(s.backendid) = u.usesysid));