From cb98e6fb8fd4f1ca955a85d5c0088e42e77a04f0 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Wed, 3 May 2006 22:45:26 +0000
Subject: [PATCH] Create a syscache for pg_database-indexed-by-oid, and make
 use of it in various places that were previously doing ad hoc pg_database
 searches. This may speed up database-related privilege checks a little bit,
 but the main motivation is to eliminate the performance reason for having
 ReverifyMyDatabase do such a lot of stuff (viz, avoiding repeat scans of
 pg_database during backend startup).  The locking reason for having that
 routine is about to go away, and it'd be good to have the option to break it
 up.

---
 src/backend/catalog/aclchk.c        | 137 ++++++++--------------------
 src/backend/commands/dbcommands.c   |  59 ++++--------
 src/backend/commands/vacuum.c       |  25 +++--
 src/backend/postmaster/autovacuum.c |  29 ++----
 src/backend/utils/cache/syscache.c  |  13 ++-
 src/backend/utils/init/postinit.c   |  17 ++--
 src/include/utils/acl.h             |   6 +-
 src/include/utils/syscache.h        |  35 +++----
 8 files changed, 116 insertions(+), 205 deletions(-)

diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index a74c28e5b3d..19c34bc49cf 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.127 2006/04/30 21:15:33 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.128 2006/05/03 22:45:26 tgl Exp $
  *
  * NOTES
  *	  See acl.h.
@@ -34,6 +34,7 @@
 #include "catalog/pg_proc.h"
 #include "catalog/pg_tablespace.h"
 #include "catalog/pg_type.h"
+#include "commands/dbcommands.h"
 #include "miscadmin.h"
 #include "parser/parse_func.h"
 #include "utils/acl.h"
@@ -412,8 +413,8 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
 		case ACL_OBJECT_SEQUENCE:
 			foreach(cell, objnames)
 			{
-				Oid			relOid;
 				RangeVar   *relvar = (RangeVar *) lfirst(cell);
+				Oid			relOid;
 
 				relOid = RangeVarGetRelid(relvar, false);
 				objects = lappend_oid(objects, relOid);
@@ -423,32 +424,15 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
 			foreach(cell, objnames)
 			{
 				char	   *dbname = strVal(lfirst(cell));
-				ScanKeyData entry[1];
-				HeapScanDesc scan;
-				HeapTuple	tuple;
-				Relation	relation;
-
-				relation = heap_open(DatabaseRelationId, AccessShareLock);
+				Oid			dbid;
 
-				/*
-				 * There's no syscache for pg_database, so we must look the
-				 * hard way.
-				 */
-				ScanKeyInit(&entry[0],
-							Anum_pg_database_datname,
-							BTEqualStrategyNumber, F_NAMEEQ,
-							CStringGetDatum(dbname));
-				scan = heap_beginscan(relation, SnapshotNow, 1, entry);
-				tuple = heap_getnext(scan, ForwardScanDirection);
-				if (!HeapTupleIsValid(tuple))
+				dbid = get_database_oid(dbname);
+				if (!OidIsValid(dbid))
 					ereport(ERROR,
 							(errcode(ERRCODE_UNDEFINED_DATABASE),
-						  errmsg("database \"%s\" does not exist", dbname)));
-				objects = lappend_oid(objects, HeapTupleGetOid(tuple));
-
-				heap_close(relation, AccessShareLock);
-
-				heap_endscan(scan);
+							 errmsg("database \"%s\" does not exist",
+									dbname)));
+				objects = lappend_oid(objects, dbid);
 			}
 			break;
 		case ACL_OBJECT_FUNCTION:
@@ -474,7 +458,8 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
 				if (!HeapTupleIsValid(tuple))
 					ereport(ERROR,
 							(errcode(ERRCODE_UNDEFINED_OBJECT),
-						errmsg("language \"%s\" does not exist", langname)));
+							 errmsg("language \"%s\" does not exist",
+									langname)));
 
 				objects = lappend_oid(objects, HeapTupleGetOid(tuple));
 
@@ -493,7 +478,8 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
 				if (!HeapTupleIsValid(tuple))
 					ereport(ERROR,
 							(errcode(ERRCODE_UNDEFINED_SCHEMA),
-						   errmsg("schema \"%s\" does not exist", nspname)));
+							 errmsg("schema \"%s\" does not exist",
+									nspname)));
 
 				objects = lappend_oid(objects, HeapTupleGetOid(tuple));
 
@@ -764,22 +750,13 @@ ExecGrant_Database(InternalGrant *istmt)
 		int			nnewmembers;
 		Oid		   *oldmembers;
 		Oid		   *newmembers;
-		ScanKeyData entry[1];
-		SysScanDesc scan;
 		HeapTuple	tuple;
 
-		/* There's no syscache for pg_database, so must look the hard way */
-		ScanKeyInit(&entry[0],
-					ObjectIdAttributeNumber,
-					BTEqualStrategyNumber, F_OIDEQ,
-					ObjectIdGetDatum(datId));
-		scan = systable_beginscan(relation, DatabaseOidIndexId, true,
-								  SnapshotNow, 1, entry);
-
-		tuple = systable_getnext(scan);
-
+		tuple = SearchSysCache(DATABASEOID,
+							   ObjectIdGetDatum(datId),
+							   0, 0, 0);
 		if (!HeapTupleIsValid(tuple))
-			elog(ERROR, "could not find tuple for database %u", datId);
+			elog(ERROR, "cache lookup failed for database %u", datId);
 
 		pg_database_tuple = (Form_pg_database) GETSTRUCT(tuple);
 
@@ -847,7 +824,7 @@ ExecGrant_Database(InternalGrant *istmt)
 							  noldmembers, oldmembers,
 							  nnewmembers, newmembers);
 
-		systable_endscan(scan);
+		ReleaseSysCache(tuple);
 
 		pfree(new_acl);
 
@@ -1657,10 +1634,11 @@ pg_database_aclmask(Oid db_oid, Oid roleid,
 					AclMode mask, AclMaskHow how)
 {
 	AclMode		result;
-	Relation	pg_database;
-	ScanKeyData entry[1];
-	SysScanDesc scan;
 	HeapTuple	tuple;
+	Datum		aclDatum;
+	bool		isNull;
+	Acl		   *acl;
+	Oid			ownerId;
 
 	/* Superusers bypass all permission checking. */
 	if (superuser_arg(roleid))
@@ -1668,50 +1646,19 @@ pg_database_aclmask(Oid db_oid, Oid roleid,
 
 	/*
 	 * Get the database's ACL from pg_database
-	 *
-	 * There's no syscache for pg_database, so must look the hard way
 	 */
-	pg_database = heap_open(DatabaseRelationId, AccessShareLock);
-	ScanKeyInit(&entry[0],
-				ObjectIdAttributeNumber,
-				BTEqualStrategyNumber, F_OIDEQ,
-				ObjectIdGetDatum(db_oid));
-	scan = systable_beginscan(pg_database, DatabaseOidIndexId, true,
-							  SnapshotNow, 1, entry);
-	tuple = systable_getnext(scan);
+	tuple = SearchSysCache(DATABASEOID,
+						   ObjectIdGetDatum(db_oid),
+						   0, 0, 0);
 	if (!HeapTupleIsValid(tuple))
 		ereport(ERROR,
 				(errcode(ERRCODE_UNDEFINED_DATABASE),
 				 errmsg("database with OID %u does not exist", db_oid)));
 
-	result = pg_database_tuple_aclmask(tuple, RelationGetDescr(pg_database),
-									   roleid, mask, how);
-
-	systable_endscan(scan);
-	heap_close(pg_database, AccessShareLock);
-
-	return result;
-}
-
-/*
- * This is split out so that ReverifyMyDatabase can perform an ACL check
- * without a whole extra search of pg_database
- */
-AclMode
-pg_database_tuple_aclmask(HeapTuple db_tuple, TupleDesc tupdesc,
-						  Oid roleid, AclMode mask, AclMaskHow how)
-{
-	AclMode		result;
-	Datum		aclDatum;
-	bool		isNull;
-	Acl		   *acl;
-	Oid			ownerId;
-
-	ownerId = ((Form_pg_database) GETSTRUCT(db_tuple))->datdba;
-
-	aclDatum = heap_getattr(db_tuple, Anum_pg_database_datacl,
-							tupdesc, &isNull);
+	ownerId = ((Form_pg_database) GETSTRUCT(tuple))->datdba;
 
+	aclDatum = SysCacheGetAttr(DATABASEOID, tuple, Anum_pg_database_datacl,
+							   &isNull);
 	if (isNull)
 	{
 		/* No ACL, so build default ACL */
@@ -1730,6 +1677,8 @@ pg_database_tuple_aclmask(HeapTuple db_tuple, TupleDesc tupdesc,
 	if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
 		pfree(acl);
 
+	ReleaseSysCache(tuple);
+
 	return result;
 }
 
@@ -2298,36 +2247,24 @@ pg_opclass_ownercheck(Oid opc_oid, Oid roleid)
 bool
 pg_database_ownercheck(Oid db_oid, Oid roleid)
 {
-	Relation	pg_database;
-	ScanKeyData entry[1];
-	SysScanDesc scan;
-	HeapTuple	dbtuple;
+	HeapTuple	tuple;
 	Oid			dba;
 
 	/* Superusers bypass all permission checking. */
 	if (superuser_arg(roleid))
 		return true;
 
-	/* There's no syscache for pg_database, so must look the hard way */
-	pg_database = heap_open(DatabaseRelationId, AccessShareLock);
-	ScanKeyInit(&entry[0],
-				ObjectIdAttributeNumber,
-				BTEqualStrategyNumber, F_OIDEQ,
-				ObjectIdGetDatum(db_oid));
-	scan = systable_beginscan(pg_database, DatabaseOidIndexId, true,
-							  SnapshotNow, 1, entry);
-
-	dbtuple = systable_getnext(scan);
-
-	if (!HeapTupleIsValid(dbtuple))
+	tuple = SearchSysCache(DATABASEOID,
+						   ObjectIdGetDatum(db_oid),
+						   0, 0, 0);
+	if (!HeapTupleIsValid(tuple))
 		ereport(ERROR,
 				(errcode(ERRCODE_UNDEFINED_DATABASE),
 				 errmsg("database with OID %u does not exist", db_oid)));
 
-	dba = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba;
+	dba = ((Form_pg_database) GETSTRUCT(tuple))->datdba;
 
-	systable_endscan(scan);
-	heap_close(pg_database, AccessShareLock);
+	ReleaseSysCache(tuple);
 
 	return has_privs_of_role(roleid, dba);
 }
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 209362782a8..b21d750394d 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.179 2006/03/29 21:17:38 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.180 2006/05/03 22:45:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -556,8 +556,6 @@ dropdb(const char *dbname, bool missing_ok)
 	Oid			db_id;
 	bool		db_istemplate;
 	Relation	pgdbrel;
-	SysScanDesc pgdbscan;
-	ScanKeyData key;
 	HeapTuple	tup;
 
 	PreventTransactionChain((void *) dbname, "DROP DATABASE");
@@ -629,31 +627,17 @@ dropdb(const char *dbname, bool missing_ok)
 						dbname)));
 
 	/*
-	 * Find the database's tuple by OID (should be unique).
+	 * Remove the database's tuple from pg_database.
 	 */
-	ScanKeyInit(&key,
-				ObjectIdAttributeNumber,
-				BTEqualStrategyNumber, F_OIDEQ,
-				ObjectIdGetDatum(db_id));
-
-	pgdbscan = systable_beginscan(pgdbrel, DatabaseOidIndexId, true,
-								  SnapshotNow, 1, &key);
-
-	tup = systable_getnext(pgdbscan);
+	tup = SearchSysCache(DATABASEOID,
+						 ObjectIdGetDatum(db_id),
+						 0, 0, 0);
 	if (!HeapTupleIsValid(tup))
-	{
-		/*
-		 * This error should never come up since the existence of the database
-		 * is checked earlier
-		 */
-		elog(ERROR, "database \"%s\" doesn't exist despite earlier reports to the contrary",
-			 dbname);
-	}
+		elog(ERROR, "cache lookup failed for database %u", db_id);
 
-	/* Remove the database's tuple from pg_database */
 	simple_heap_delete(pgdbrel, &tup->t_self);
 
-	systable_endscan(pgdbscan);
+	ReleaseSysCache(tup);
 
 	/*
 	 * Delete any comments associated with the database
@@ -1262,7 +1246,10 @@ get_database_oid(const char *dbname)
 	HeapTuple	dbtuple;
 	Oid			oid;
 
-	/* There's no syscache for pg_database, so must look the hard way */
+	/*
+	 * There's no syscache for pg_database indexed by name,
+	 * so we must look the hard way.
+	 */
 	pg_database = heap_open(DatabaseRelationId, AccessShareLock);
 	ScanKeyInit(&entry[0],
 				Anum_pg_database_datname,
@@ -1296,32 +1283,20 @@ get_database_oid(const char *dbname)
 char *
 get_database_name(Oid dbid)
 {
-	Relation	pg_database;
-	ScanKeyData entry[1];
-	SysScanDesc scan;
 	HeapTuple	dbtuple;
 	char	   *result;
 
-	/* There's no syscache for pg_database, so must look the hard way */
-	pg_database = heap_open(DatabaseRelationId, AccessShareLock);
-	ScanKeyInit(&entry[0],
-				ObjectIdAttributeNumber,
-				BTEqualStrategyNumber, F_OIDEQ,
-				ObjectIdGetDatum(dbid));
-	scan = systable_beginscan(pg_database, DatabaseOidIndexId, true,
-							  SnapshotNow, 1, entry);
-
-	dbtuple = systable_getnext(scan);
-
-	/* We assume that there can be at most one matching tuple */
+	dbtuple = SearchSysCache(DATABASEOID,
+							 ObjectIdGetDatum(dbid),
+							 0, 0, 0);
 	if (HeapTupleIsValid(dbtuple))
+	{
 		result = pstrdup(NameStr(((Form_pg_database) GETSTRUCT(dbtuple))->datname));
+		ReleaseSysCache(dbtuple);
+	}
 	else
 		result = NULL;
 
-	systable_endscan(scan);
-	heap_close(pg_database, AccessShareLock);
-
 	return result;
 }
 
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index a5d704c1d86..7f13bae8099 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.328 2006/05/02 22:25:10 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.329 2006/05/03 22:45:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,6 +28,7 @@
 #include "access/subtrans.h"
 #include "access/xlog.h"
 #include "catalog/catalog.h"
+#include "catalog/indexing.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_database.h"
 #include "catalog/pg_index.h"
@@ -767,27 +768,33 @@ vac_update_dbstats(Oid dbid,
 {
 	Relation	relation;
 	ScanKeyData entry[1];
-	HeapScanDesc scan;
+	SysScanDesc	scan;
 	HeapTuple	tuple;
+	Buffer		buf;
 	Form_pg_database dbform;
 
 	relation = heap_open(DatabaseRelationId, RowExclusiveLock);
 
-	/* Must use a heap scan, since there's no syscache for pg_database */
 	ScanKeyInit(&entry[0],
 				ObjectIdAttributeNumber,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(dbid));
 
-	scan = heap_beginscan(relation, SnapshotNow, 1, entry);
+	scan = systable_beginscan(relation, DatabaseOidIndexId, true,
+							  SnapshotNow, 1, entry);
 
-	tuple = heap_getnext(scan, ForwardScanDirection);
+	tuple = systable_getnext(scan);
 
 	if (!HeapTupleIsValid(tuple))
 		elog(ERROR, "could not find tuple for database %u", dbid);
 
+	if (scan->irel)
+		buf = scan->iscan->xs_cbuf;
+	else
+		buf = scan->scan->rs_cbuf;
+
 	/* ensure no one else does this at the same time */
-	LockBuffer(scan->rs_cbuf, BUFFER_LOCK_EXCLUSIVE);
+	LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
 
 	dbform = (Form_pg_database) GETSTRUCT(tuple);
 
@@ -795,14 +802,14 @@ vac_update_dbstats(Oid dbid,
 	dbform->datvacuumxid = vacuumXID;
 	dbform->datfrozenxid = frozenXID;
 
-	MarkBufferDirty(scan->rs_cbuf);
+	MarkBufferDirty(buf);
 
-	LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
+	LockBuffer(buf, BUFFER_LOCK_UNLOCK);
 
 	/* invalidate the tuple in the cache so we'll see the change in cache */
 	CacheInvalidateHeapTuple(relation, tuple);
 
-	heap_endscan(scan);
+	systable_endscan(scan);
 
 	heap_close(relation, RowExclusiveLock);
 
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 4a5a05c1b28..a19e504b0ef 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.17 2006/04/27 15:57:10 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.18 2006/05/03 22:45:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -46,6 +46,7 @@
 #include "utils/memutils.h"
 #include "utils/ps_status.h"
 #include "utils/relcache.h"
+#include "utils/syscache.h"
 
 
 /*
@@ -493,9 +494,6 @@ autovac_get_database_list(void)
 static void
 process_whole_db(void)
 {
-	Relation	dbRel;
-	ScanKeyData entry[1];
-	SysScanDesc scan;
 	HeapTuple	tup;
 	Form_pg_database dbForm;
 	bool		freeze;
@@ -511,21 +509,12 @@ process_whole_db(void)
 	 */
 	pgstat_vacuum_tabstat();
 
-	dbRel = heap_open(DatabaseRelationId, AccessShareLock);
-
-	/* Must use a table scan, since there's no syscache for pg_database */
-	ScanKeyInit(&entry[0],
-				ObjectIdAttributeNumber,
-				BTEqualStrategyNumber, F_OIDEQ,
-				ObjectIdGetDatum(MyDatabaseId));
-
-	scan = systable_beginscan(dbRel, DatabaseOidIndexId, true,
-							  SnapshotNow, 1, entry);
-
-	tup = systable_getnext(scan);
-
+	/* Look up the pg_database entry and decide whether to FREEZE */
+	tup = SearchSysCache(DATABASEOID,
+						 ObjectIdGetDatum(MyDatabaseId),
+						 0, 0, 0);
 	if (!HeapTupleIsValid(tup))
-		elog(ERROR, "could not find tuple for database %u", MyDatabaseId);
+		elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
 
 	dbForm = (Form_pg_database) GETSTRUCT(tup);
 
@@ -534,9 +523,7 @@ process_whole_db(void)
 	else
 		freeze = false;
 
-	systable_endscan(scan);
-
-	heap_close(dbRel, AccessShareLock);
+	ReleaseSysCache(tup);
 
 	elog(DEBUG2, "autovacuum: VACUUM%s whole database",
 		 (freeze) ? " FREEZE" : "");
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index 90b9c4cb053..ffcb26e3c55 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.102 2006/03/05 15:58:45 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.103 2006/05/03 22:45:26 tgl Exp $
  *
  * NOTES
  *	  These routines allow the parser/planner/executor to perform
@@ -31,6 +31,7 @@
 #include "catalog/pg_auth_members.h"
 #include "catalog/pg_cast.h"
 #include "catalog/pg_conversion.h"
+#include "catalog/pg_database.h"
 #include "catalog/pg_index.h"
 #include "catalog/pg_inherits.h"
 #include "catalog/pg_language.h"
@@ -273,6 +274,16 @@ static const struct cachedesc cacheinfo[] = {
 			0,
 			0
 	}},
+	{DatabaseRelationId,		/* DATABASEOID */
+		DatabaseOidIndexId,
+		0,
+		1,
+		{
+			ObjectIdAttributeNumber,
+			0,
+			0,
+			0
+	}},
 	{IndexRelationId,			/* INDEXRELID */
 		IndexRelidIndexId,
 		Anum_pg_index_indrelid,
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index e89df5bb3af..4ddc7f712af 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.164 2006/04/30 21:15:33 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.165 2006/05/03 22:45:26 tgl Exp $
  *
  *
  *-------------------------------------------------------------------------
@@ -195,19 +195,16 @@ ReverifyMyDatabase(const char *name, bool am_superuser)
 					name)));
 
 		/*
-		 * Check privilege to connect to the database.  To avoid making
-		 * a whole extra search of pg_database here, we don't go through
-		 * pg_database_aclcheck, but instead use a lower-level routine
-		 * that we can pass the pg_database tuple to.
+		 * Check privilege to connect to the database.  (The am_superuser
+		 * test is redundant, but since we have the flag, might as well
+		 * check it and save a few cycles.)
 		 */
 		if (!am_superuser &&
-			pg_database_tuple_aclmask(tup, RelationGetDescr(pgdbrel),
-									  GetUserId(),
-									  ACL_CONNECT, ACLMASK_ANY) == 0)
+			pg_database_aclcheck(MyDatabaseId, GetUserId(),
+								 ACL_CONNECT) != ACLCHECK_OK)
 			ereport(FATAL,
 					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-					 errmsg("permission denied for database %s",
-							NameStr(dbform->datname)),
+					 errmsg("permission denied for database \"%s\"", name),
 					 errdetail("User does not have CONNECT privilege.")));
 
 		/*
diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h
index 7651fba290c..27aaf0dfbf7 100644
--- a/src/include/utils/acl.h
+++ b/src/include/utils/acl.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.95 2006/04/30 21:15:33 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.96 2006/05/03 22:45:26 tgl Exp $
  *
  * NOTES
  *	  An ACL array is simply an array of AclItems, representing the union
@@ -24,8 +24,6 @@
 #ifndef ACL_H
 #define ACL_H
 
-#include "access/htup.h"
-#include "access/tupdesc.h"
 #include "nodes/parsenodes.h"
 #include "utils/array.h"
 
@@ -252,8 +250,6 @@ extern AclMode pg_class_aclmask(Oid table_oid, Oid roleid,
 				 AclMode mask, AclMaskHow how);
 extern AclMode pg_database_aclmask(Oid db_oid, Oid roleid,
 					AclMode mask, AclMaskHow how);
-extern AclMode pg_database_tuple_aclmask(HeapTuple db_tuple, TupleDesc tupdesc,
-					Oid roleid, AclMode mask, AclMaskHow how);
 extern AclMode pg_proc_aclmask(Oid proc_oid, Oid roleid,
 				AclMode mask, AclMaskHow how);
 extern AclMode pg_language_aclmask(Oid lang_oid, Oid roleid,
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index d3feea1f82b..34ef6132b3e 100644
--- a/src/include/utils/syscache.h
+++ b/src/include/utils/syscache.h
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/syscache.h,v 1.62 2006/03/05 15:59:08 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/syscache.h,v 1.63 2006/05/03 22:45:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -46,22 +46,23 @@
 #define CONDEFAULT		15
 #define CONNAMENSP		16
 #define CONOID			17
-#define INDEXRELID		18
-#define INHRELID		19
-#define LANGNAME		20
-#define LANGOID			21
-#define NAMESPACENAME	22
-#define NAMESPACEOID	23
-#define OPERNAMENSP		24
-#define OPEROID			25
-#define PROCNAMEARGSNSP 26
-#define PROCOID			27
-#define RELNAMENSP		28
-#define RELOID			29
-#define RULERELNAME		30
-#define STATRELATT		31
-#define TYPENAMENSP		32
-#define TYPEOID			33
+#define DATABASEOID		18
+#define INDEXRELID		19
+#define INHRELID		20
+#define LANGNAME		21
+#define LANGOID			22
+#define NAMESPACENAME	23
+#define NAMESPACEOID	24
+#define OPERNAMENSP		25
+#define OPEROID			26
+#define PROCNAMEARGSNSP 27
+#define PROCOID			28
+#define RELNAMENSP		29
+#define RELOID			30
+#define RULERELNAME		31
+#define STATRELATT		32
+#define TYPENAMENSP		33
+#define TYPEOID			34
 
 extern void InitCatalogCache(void);
 extern void InitCatalogCachePhase2(void);
-- 
GitLab