diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 28ec8d648ef9579db987582745fe88b91ec148f7..c650ff88a1a27dad25b955b03064aad24b09aae9 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.19 2001/06/06 21:29:17 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.20 2001/06/13 21:44:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -193,16 +193,18 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
 	ReleaseSysCache(tuple);
 
 	/*
-	 * Open the class, getting only a read lock on it, and check permissions
+	 * Open the class, getting only a read lock on it, and check permissions.
+	 * Permissions check should match vacuum's check!
 	 */
 	onerel = heap_open(relid, AccessShareLock);
 
-	if (!pg_ownercheck(GetUserId(), RelationGetRelationName(onerel),
-					   RELNAME))
+	if (! (pg_ownercheck(GetUserId(), RelationGetRelationName(onerel),
+						 RELNAME) ||
+		   (is_dbadmin(MyDatabaseId) && !onerel->rd_rel->relisshared)))
 	{
 		/* No need for a notice if we already complained during VACUUM */
 		if (!vacstmt->vacuum)
-			elog(NOTICE, "Skipping \"%s\" --- only table owner can ANALYZE it",
+			elog(NOTICE, "Skipping \"%s\" --- only table or database owner can ANALYZE it",
 				 RelationGetRelationName(onerel));
 		heap_close(onerel, NoLock);
 		CommitTransactionCommand();
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
index 695c7401e719cdf499ab2e475d375b99080b7dbb..39668f867e068b7ac9288df21ea205f6d6edba17 100644
--- a/src/backend/commands/comment.c
+++ b/src/backend/commands/comment.c
@@ -4,10 +4,10 @@
  *
  * PostgreSQL object comments utility code.
  *
- * Copyright (c) 1999, PostgreSQL Global Development Group
+ * Copyright (c) 1999-2001, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.29 2001/06/05 19:34:56 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.30 2001/06/13 21:44:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,7 +21,6 @@
 #include "catalog/pg_database.h"
 #include "catalog/pg_description.h"
 #include "catalog/pg_operator.h"
-#include "catalog/pg_shadow.h"
 #include "catalog/pg_trigger.h"
 #include "catalog/pg_type.h"
 #include "catalog/pg_class.h"
@@ -389,16 +388,11 @@ CommentAttribute(char *relname, char *attrname, char *comment)
 static void
 CommentDatabase(char *database, char *comment)
 {
-
 	Relation	pg_database;
-	HeapTuple	dbtuple,
-				usertuple;
 	ScanKeyData entry;
 	HeapScanDesc scan;
+	HeapTuple	dbtuple;
 	Oid			oid;
-	bool		superuser;
-	int32		dba;
-	Oid			userid;
 
 	/*** First find the tuple in pg_database for the database ***/
 
@@ -408,33 +402,17 @@ CommentDatabase(char *database, char *comment)
 	scan = heap_beginscan(pg_database, 0, SnapshotNow, 1, &entry);
 	dbtuple = heap_getnext(scan, 0);
 
-	/*** Validate database exists, and fetch the dba id and oid ***/
+	/*** Validate database exists, and fetch the db oid ***/
 
 	if (!HeapTupleIsValid(dbtuple))
 		elog(ERROR, "database '%s' does not exist", database);
-	dba = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba;
 	oid = dbtuple->t_data->t_oid;
 
-	/*** Now, fetch user information ***/
-
-	userid = GetUserId();
-	usertuple = SearchSysCache(SHADOWSYSID,
-							   ObjectIdGetDatum(userid),
-							   0, 0, 0);
-	if (!HeapTupleIsValid(usertuple))
-		elog(ERROR, "invalid user id %u", (unsigned) userid);
-	superuser = ((Form_pg_shadow) GETSTRUCT(usertuple))->usesuper;
-	ReleaseSysCache(usertuple);
+	/*** Allow if the user matches the database dba or is a superuser ***/
 
-	/*** Allow if the userid matches the database dba or is a superuser ***/
-
-#ifndef NO_SECURITY
-	if (!(superuser || (userid == dba)))
-	{
+	if (!(superuser() || is_dbadmin(oid)))
 		elog(ERROR, "you are not permitted to comment on database '%s'",
 			 database);
-	}
-#endif
 
 	/*** Create the comments with the pg_database oid ***/
 
@@ -444,7 +422,6 @@ CommentDatabase(char *database, char *comment)
 
 	heap_endscan(scan);
 	heap_close(pg_database, AccessShareLock);
-
 }
 
 /*------------------------------------------------------------------
diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c
index 98a6e351476f06e917c8fcdf2c717c794ffc2727..b5852b6fffaea6398695d03009a835ac155b4128 100644
--- a/src/backend/commands/define.c
+++ b/src/backend/commands/define.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.55 2001/05/18 21:24:18 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.56 2001/06/13 21:44:40 tgl Exp $
  *
  * DESCRIPTION
  *	  The "DefineFoo" routines take the parse tree and pick out the
@@ -33,21 +33,21 @@
  *
  *-------------------------------------------------------------------------
  */
+#include "postgres.h"
+
 #include <ctype.h>
 #include <math.h>
 
-#include "postgres.h"
-
 #include "access/heapam.h"
 #include "catalog/catname.h"
 #include "catalog/pg_aggregate.h"
 #include "catalog/pg_language.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_proc.h"
-#include "catalog/pg_shadow.h"
 #include "catalog/pg_type.h"
 #include "commands/defrem.h"
 #include "fmgr.h"
+#include "miscadmin.h"
 #include "optimizer/cost.h"
 #include "parser/parse_expr.h"
 #include "tcop/dest.h"
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 373a68fbf30e2b02bacc2ca10a1b3ca1ea120001..108c4ea3780863db0782614d49df7eaac1c74a4f 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.49 2001/05/31 18:16:55 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.50 2001/06/13 21:44:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,7 +28,6 @@
 #include "catalog/pg_opclass.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_proc.h"
-#include "catalog/pg_shadow.h"
 #include "commands/defrem.h"
 #include "miscadmin.h"
 #include "optimizer/clauses.h"
@@ -712,14 +711,9 @@ ReindexTable(const char *name, bool force)
 void
 ReindexDatabase(const char *dbname, bool force, bool all)
 {
-	Relation	relation,
-				relationRelation;
-	HeapTuple	dbtuple,
-				tuple;
+	Relation	relationRelation;
 	HeapScanDesc scan;
-	int4		db_owner;
-	Oid			db_id;
-	ScanKeyData scankey;
+	HeapTuple	tuple;
 	MemoryContext private_context;
 	MemoryContext old;
 	int			relcnt,
@@ -730,24 +724,12 @@ ReindexDatabase(const char *dbname, bool force, bool all)
 
 	AssertArg(dbname);
 
-	relation = heap_openr(DatabaseRelationName, AccessShareLock);
-	ScanKeyEntryInitialize(&scankey, 0, Anum_pg_database_datname,
-						   F_NAMEEQ, NameGetDatum(dbname));
-	scan = heap_beginscan(relation, 0, SnapshotNow, 1, &scankey);
-	dbtuple = heap_getnext(scan, 0);
-	if (!HeapTupleIsValid(dbtuple))
-		elog(ERROR, "Database \"%s\" does not exist", dbname);
-	db_id = dbtuple->t_data->t_oid;
-	db_owner = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba;
-	heap_endscan(scan);
-	heap_close(relation, NoLock);
+	if (strcmp(dbname, DatabaseName) != 0)
+		elog(ERROR, "REINDEX DATABASE: Can be executed only on the currently open database.");
 
-	if (GetUserId() != db_owner && !superuser())
+	if (! (superuser() || is_dbadmin(MyDatabaseId)))
 		elog(ERROR, "REINDEX DATABASE: Permission denied.");
 
-	if (db_id != MyDatabaseId)
-		elog(ERROR, "REINDEX DATABASE: Can be executed only on the currently open database.");
-
 	/*
 	 * We cannot run inside a user transaction block; if we were inside a
 	 * transaction, then our commit- and start-transaction-command calls
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 43327c7a65ac1a21618174d66399aaf5be89196f..120c5d8b008c8f0865c74c0fd4b0c6b2871f3258 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -3,20 +3,26 @@
  * proclang.c
  *	  PostgreSQL PROCEDURAL LANGUAGE support code.
  *
+ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.28 2001/06/13 21:44:40 tgl Exp $
+ *
  *-------------------------------------------------------------------------
  */
-#include <ctype.h>
-
 #include "postgres.h"
 
+#include <ctype.h>
+
 #include "access/heapam.h"
 #include "catalog/catname.h"
 #include "catalog/indexing.h"
 #include "catalog/pg_language.h"
 #include "catalog/pg_proc.h"
-#include "catalog/pg_shadow.h"
 #include "commands/proclang.h"
 #include "fmgr.h"
+#include "miscadmin.h"
 #include "utils/builtins.h"
 #include "utils/syscache.h"
 
@@ -63,10 +69,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 	 * Check permission
 	 */
 	if (!superuser())
-	{
 		elog(ERROR, "Only users with Postgres superuser privilege are "
 			 "permitted to create procedural languages");
-	}
 
 	/*
 	 * Translate the language name and check that this language doesn't
@@ -150,10 +154,8 @@ DropProceduralLanguage(DropPLangStmt *stmt)
 	 * Check permission
 	 */
 	if (!superuser())
-	{
 		elog(ERROR, "Only users with Postgres superuser privilege are "
 			 "permitted to drop procedural languages");
-	}
 
 	/*
 	 * Translate the language name, check that this language exist and is
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 3cba03952015fa4cf681973bbe9e7dd058ee83bb..33d5409364ac9166376c83d4c0867f9ba17aca47 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.195 2001/05/25 15:45:32 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.196 2001/06/13 21:44:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -437,15 +437,20 @@ vacuum_rel(Oid relid)
 	/*
 	 * Open the class, get an exclusive lock on it, and check permissions.
 	 *
+	 * We allow the user to vacuum a table if he is superuser, the table
+	 * owner, or the database owner (but in the latter case, only if it's
+	 * not a shared relation).  pg_ownercheck includes the superuser case.
+	 *
 	 * Note we choose to treat permissions failure as a NOTICE and keep
 	 * trying to vacuum the rest of the DB --- is this appropriate?
 	 */
 	onerel = heap_open(relid, AccessExclusiveLock);
 
-	if (!pg_ownercheck(GetUserId(), RelationGetRelationName(onerel),
-					   RELNAME))
+	if (! (pg_ownercheck(GetUserId(), RelationGetRelationName(onerel),
+						 RELNAME) ||
+		   (is_dbadmin(MyDatabaseId) && !onerel->rd_rel->relisshared)))
 	{
-		elog(NOTICE, "Skipping \"%s\" --- only table owner can VACUUM it",
+		elog(NOTICE, "Skipping \"%s\" --- only table or database owner can VACUUM it",
 			 RelationGetRelationName(onerel));
 		heap_close(onerel, AccessExclusiveLock);
 		CommitTransactionCommand();
diff --git a/src/backend/libpq/be-fsstubs.c b/src/backend/libpq/be-fsstubs.c
index 4d50ee1ae12d907d744f603d1440570a2d824d48..b0a759bc0080fbaf17009679bb305ad925a87010 100644
--- a/src/backend/libpq/be-fsstubs.c
+++ b/src/backend/libpq/be-fsstubs.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/libpq/be-fsstubs.c,v 1.58 2001/03/22 03:59:30 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/libpq/be-fsstubs.c,v 1.59 2001/06/13 21:44:41 tgl Exp $
  *
  * NOTES
  *	  This should be moved to a more appropriate place.  It is here
@@ -39,9 +39,9 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
-#include "catalog/pg_shadow.h"
 #include "libpq/be-fsstubs.h"
 #include "libpq/libpq-fs.h"
+#include "miscadmin.h"
 #include "storage/large_object.h"
 #include "utils/memutils.h"
 
diff --git a/src/backend/utils/misc/superuser.c b/src/backend/utils/misc/superuser.c
index e539d57347bc647377f05adbaf81a1406a89dc16..73cfe8cb9799b9bad3750abc8719fca43ae3bdc5 100644
--- a/src/backend/utils/misc/superuser.c
+++ b/src/backend/utils/misc/superuser.c
@@ -1,35 +1,38 @@
 /*-------------------------------------------------------------------------
  *
  * superuser.c
- *
  *	  The superuser() function.  Determines if user has superuser privilege.
+ *	  Also, a function to check for the owner (datdba) of a database.
+ *
  *
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.17 2001/01/24 19:43:16 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.18 2001/06/13 21:44:41 tgl Exp $
  *
- * DESCRIPTION
- *	  See superuser().
  *-------------------------------------------------------------------------
  */
-
 #include "postgres.h"
+
+#include "access/heapam.h"
+#include "catalog/catname.h"
+#include "catalog/pg_database.h"
 #include "catalog/pg_shadow.h"
 #include "utils/syscache.h"
 #include "miscadmin.h"
+#include "utils/fmgroids.h"
 
+
+/*
+ * The Postgres user running this command has Postgres superuser privileges
+ */
 bool
 superuser(void)
 {
-/*--------------------------------------------------------------------------
-	The Postgres user running this command has Postgres superuser
-	privileges.
---------------------------------------------------------------------------*/
+	bool		result = false;
 	HeapTuple	utup;
-	bool		result;
 
 	utup = SearchSysCache(SHADOWSYSID,
 						  ObjectIdGetDatum(GetUserId()),
@@ -38,7 +41,36 @@ superuser(void)
 	{
 		result = ((Form_pg_shadow) GETSTRUCT(utup))->usesuper;
 		ReleaseSysCache(utup);
-		return result;
 	}
-	return false;
+	return result;
+}
+
+/*
+ * The Postgres user running this command is the owner of the specified
+ * database.
+ */
+bool
+is_dbadmin(Oid dbid)
+{
+	Relation	pg_database;
+	ScanKeyData entry[1];
+	HeapScanDesc scan;
+	HeapTuple	dbtuple;
+	int32		dba;
+
+	/* There's no syscache for pg_database, so must look the hard way */
+	pg_database = heap_openr(DatabaseRelationName, AccessShareLock);
+	ScanKeyEntryInitialize(&entry[0], 0x0,
+						   ObjectIdAttributeNumber, F_OIDEQ,
+						   ObjectIdGetDatum(dbid));
+	scan = heap_beginscan(pg_database, 0, SnapshotNow, 1, entry);
+	dbtuple = heap_getnext(scan, 0);
+	if (!HeapTupleIsValid(dbtuple))
+		elog(ERROR, "database %u does not exist", dbid);
+	dba = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba;
+	heap_endscan(scan);
+	heap_close(pg_database, AccessShareLock);
+
+	/* XXX some confusion about whether userids are OID or int4 ... */
+	return (GetUserId() == (Oid) dba);
 }
diff --git a/src/include/catalog/pg_shadow.h b/src/include/catalog/pg_shadow.h
index e0b087a9d913f54c95487285ff3cd6bccde57398..fdec3fa82cace5a60c96eeb7121bb49952cbcd0e 100644
--- a/src/include/catalog/pg_shadow.h
+++ b/src/include/catalog/pg_shadow.h
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_shadow.h,v 1.11 2001/03/09 22:10:13 tgl Exp $
+ * $Id: pg_shadow.h,v 1.12 2001/06/13 21:44:41 tgl Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -24,10 +24,6 @@
 #define PG_SHADOW_H
 
 
-/* Prototype required for superuser() from superuser.c */
-
-bool		superuser(void);
-
 /* ----------------
  *		pg_shadow definition.  cpp turns this into
  *		typedef struct FormData_pg_shadow
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 742f58137c5e9fcc90581ee1e6e0cb8c8e5a969f..588c2f99dea2990d690a7a3f6024feff183ef6cc 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: miscadmin.h,v 1.85 2001/05/12 01:48:49 petere Exp $
+ * $Id: miscadmin.h,v 1.86 2001/06/13 21:44:41 tgl Exp $
  *
  * NOTES
  *	  some of the information in this file should be moved to
@@ -220,9 +220,13 @@ extern int	CheckPathAccess(char *path, char *name, int open_mode);
 extern void GetCharSetByHost(char *TableName, int host, const char *DataDir);
 extern void SetCharSet(void);
 extern char *convertstr(unsigned char *buff, int len, int dest);
-
 #endif
 
+/* in utils/misc/superuser.c */
+extern bool superuser(void);	/* current user is superuser */
+extern bool is_dbadmin(Oid dbid); /* current user is owner of database */
+
+
 /*****************************************************************************
  *	  pmod.h --																 *
  *			POSTGRES processing mode definitions.							 *