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.
*
*
* 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.
#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"
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);
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:
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));
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));
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);
noldmembers, oldmembers,
nnewmembers, newmembers);
- systable_endscan(scan);
+ ReleaseSysCache(tuple);
pfree(new_acl);
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))
/*
* 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 */
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
pfree(acl);
+ ReleaseSysCache(tuple);
+
return result;
}
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);
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
Oid db_id;
bool db_istemplate;
Relation pgdbrel;
- SysScanDesc pgdbscan;
- ScanKeyData key;
HeapTuple tup;
PreventTransactionChain((void *) dbname, "DROP DATABASE");
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
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,
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;
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#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"
{
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);
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);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#include "utils/memutils.h"
#include "utils/ps_status.h"
#include "utils/relcache.h"
+#include "utils/syscache.h"
/*
static void
process_whole_db(void)
{
- Relation dbRel;
- ScanKeyData entry[1];
- SysScanDesc scan;
HeapTuple tup;
Form_pg_database dbForm;
bool freeze;
*/
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);
else
freeze = false;
- systable_endscan(scan);
-
- heap_close(dbRel, AccessShareLock);
+ ReleaseSysCache(tup);
elog(DEBUG2, "autovacuum: VACUUM%s whole database",
(freeze) ? " FREEZE" : "");
*
*
* 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
#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"
0,
0
}},
+ {DatabaseRelationId, /* DATABASEOID */
+ DatabaseOidIndexId,
+ 0,
+ 1,
+ {
+ ObjectIdAttributeNumber,
+ 0,
+ 0,
+ 0
+ }},
{IndexRelationId, /* INDEXRELID */
IndexRelidIndexId,
Anum_pg_index_indrelid,
*
*
* 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 $
*
*
*-------------------------------------------------------------------------
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.")));
/*
* 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
#ifndef ACL_H
#define ACL_H
-#include "access/htup.h"
-#include "access/tupdesc.h"
#include "nodes/parsenodes.h"
#include "utils/array.h"
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,
* 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 $
*
*-------------------------------------------------------------------------
*/
#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);