aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/misc/superuser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/misc/superuser.c')
-rw-r--r--src/backend/utils/misc/superuser.c69
1 files changed, 59 insertions, 10 deletions
diff --git a/src/backend/utils/misc/superuser.c b/src/backend/utils/misc/superuser.c
index ee6cc397e34..520dc470cdc 100644
--- a/src/backend/utils/misc/superuser.c
+++ b/src/backend/utils/misc/superuser.c
@@ -2,7 +2,11 @@
*
* 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_shadow.usesuper directly, so that the escape hatch built in for
+ * the single-user case works.
*
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
@@ -10,26 +14,33 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/misc/superuser.c,v 1.30 2004/12/31 22:02:45 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/misc/superuser.c,v 1.31 2005/05/29 20:38:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
-#include "access/heapam.h"
#include "catalog/pg_shadow.h"
-#include "commands/dbcommands.h"
+#include "utils/inval.h"
#include "utils/syscache.h"
#include "miscadmin.h"
/*
+ * In common cases the same userid (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 userid. The cache can be flushed
+ * at need by watching for cache update events on pg_shadow.
+ */
+static AclId last_userid = 0; /* 0 == cache not valid */
+static bool last_userid_is_super = false;
+static bool userid_callback_registered = false;
+
+static void UseridCallback(Datum arg, Oid relid);
+
+
+/*
* 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)
@@ -38,16 +49,24 @@ superuser(void)
}
+/*
+ * The specified userid has Postgres superuser privileges
+ */
bool
superuser_arg(AclId userid)
{
- bool result = false;
+ bool result;
HeapTuple utup;
+ /* Quick out for cache hit */
+ if (AclIdIsValid(last_userid) && last_userid == userid)
+ return last_userid_is_super;
+
/* Special escape path in case you deleted all your users. */
if (!IsUnderPostmaster && userid == BOOTSTRAP_USESYSID)
return true;
+ /* OK, look up the information in pg_shadow */
utup = SearchSysCache(SHADOWSYSID,
Int32GetDatum(userid),
0, 0, 0);
@@ -56,5 +75,35 @@ superuser_arg(AclId userid)
result = ((Form_pg_shadow) GETSTRUCT(utup))->usesuper;
ReleaseSysCache(utup);
}
+ else
+ {
+ /* Report "not superuser" for invalid userids */
+ result = false;
+ }
+
+ /* If first time through, set up callback for cache flushes */
+ if (!userid_callback_registered)
+ {
+ CacheRegisterSyscacheCallback(SHADOWSYSID,
+ UseridCallback,
+ (Datum) 0);
+ userid_callback_registered = true;
+ }
+
+ /* Cache the result for next time */
+ last_userid = userid;
+ last_userid_is_super = result;
+
return result;
}
+
+/*
+ * UseridCallback
+ * Syscache inval callback function
+ */
+static void
+UseridCallback(Datum arg, Oid relid)
+{
+ /* Invalidate our local cache in case user's superuserness changed */
+ last_userid = 0;
+}