*
* superuser.c
* The superuser() function. Determines if user has superuser privilege.
- * Also, a function to check for the owner (datdba) of a database.
*
+ * All code should use either of these two functions to find out
+ * whether a given user is a superuser, rather than examining
+ * pg_authid.rolsuper directly, so that the escape hatch built in for
+ * the single-user case works.
*
- * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
+ *
+ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/misc/superuser.c,v 1.28 2003/11/29 19:52:04 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/misc/superuser.c,v 1.38 2008/09/09 18:58:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
-#include "access/heapam.h"
-#include "catalog/pg_shadow.h"
-#include "commands/dbcommands.h"
+#include "catalog/pg_authid.h"
+#include "utils/inval.h"
#include "utils/syscache.h"
#include "miscadmin.h"
+/*
+ * In common cases the same roleid (ie, the session or current ID) will
+ * be queried repeatedly. So we maintain a simple one-entry cache for
+ * the status of the last requested roleid. The cache can be flushed
+ * at need by watching for cache update events on pg_authid.
+ */
+static Oid last_roleid = InvalidOid; /* InvalidOid == cache not valid */
+static bool last_roleid_is_super = false;
+static bool roleid_callback_registered = false;
+
+static void RoleidCallback(Datum arg, int cacheid, ItemPointer tuplePtr);
+
+
/*
* The Postgres user running this command has Postgres superuser privileges
- *
- * All code should use either of these two functions to find out
- * whether a given user is a superuser, rather than evaluating
- * pg_shadow.usesuper directly, so that the escape hatch built in for
- * the single-user case works.
*/
bool
superuser(void)
}
+/*
+ * The specified role has Postgres superuser privileges
+ */
bool
-superuser_arg(AclId userid)
+superuser_arg(Oid roleid)
{
- bool result = false;
- HeapTuple utup;
+ bool result;
+ HeapTuple rtup;
+
+ /* Quick out for cache hit */
+ if (OidIsValid(last_roleid) && last_roleid == roleid)
+ return last_roleid_is_super;
/* Special escape path in case you deleted all your users. */
- if (!IsUnderPostmaster && userid == BOOTSTRAP_USESYSID)
+ if (!IsUnderPostmaster && roleid == BOOTSTRAP_SUPERUSERID)
return true;
- utup = SearchSysCache(SHADOWSYSID,
- Int32GetDatum(userid),
+ /* OK, look up the information in pg_authid */
+ rtup = SearchSysCache(AUTHOID,
+ ObjectIdGetDatum(roleid),
0, 0, 0);
- if (HeapTupleIsValid(utup))
+ if (HeapTupleIsValid(rtup))
+ {
+ result = ((Form_pg_authid) GETSTRUCT(rtup))->rolsuper;
+ ReleaseSysCache(rtup);
+ }
+ else
{
- result = ((Form_pg_shadow) GETSTRUCT(utup))->usesuper;
- ReleaseSysCache(utup);
+ /* Report "not superuser" for invalid roleids */
+ result = false;
}
+
+ /* If first time through, set up callback for cache flushes */
+ if (!roleid_callback_registered)
+ {
+ CacheRegisterSyscacheCallback(AUTHOID,
+ RoleidCallback,
+ (Datum) 0);
+ roleid_callback_registered = true;
+ }
+
+ /* Cache the result for next time */
+ last_roleid = roleid;
+ last_roleid_is_super = result;
+
return result;
}
+
+/*
+ * UseridCallback
+ * Syscache inval callback function
+ */
+static void
+RoleidCallback(Datum arg, int cacheid, ItemPointer tuplePtr)
+{
+ /* Invalidate our local cache in case role's superuserness changed */
+ last_roleid = InvalidOid;
+}